diff options
Diffstat (limited to 'vendor/voclient/voapps')
93 files changed, 33254 insertions, 0 deletions
diff --git a/vendor/voclient/voapps/.BASE b/vendor/voclient/voapps/.BASE new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/vendor/voclient/voapps/.BASE diff --git a/vendor/voclient/voapps/Makefile b/vendor/voclient/voapps/Makefile new file mode 100644 index 00000000..ed6e30df --- /dev/null +++ b/vendor/voclient/voapps/Makefile @@ -0,0 +1,314 @@ +#/////////////////////////////////////////////////////////////////////////////// +#// +#// Makefile for the VOClient Package Applications +#// +#/////////////////////////////////////////////////////////////////////////////// + +# primary dependencies + +NAME = VOApps +VERSION = 1.0 +PLATFORM := $(shell uname -s) +PLMACH := $(shell uname -m) +HERE := $(shell /bin/pwd) +BINDIR := ../bin/ +LIBDIR := ../lib/ +INCDIR := ../include/ + + +# secondary dependencies +LIBBASE = lib$(NAME) +STATICLIB = $(HERE)/$(LIBBASE).a +SHAREDLIB = $(HERE)/$(LIBBASE).so.$(VERSION) + + +# stuff that's precious to keep +.PRECIOUS: $(STATICLIB) $(SHAREDLIB) +.KEEP_STATE: + + +# includes, flags and libraries +CC = gcc +CINCS = -I$(HERE) -I../ -I$(INCDIR) -I../../../include +LFLAGS = -L../ -L../lib/ -L../../../bin/ + +#F77 = g77 +F77 = gfortran +FFLAGS = -g -Wall + + +ifeq ($(PLATFORM),Darwin) + LIBCURL = -lcurl +else + LIBCURL = ../lib/libcurl.a +endif +LIBCFITSIO = ../lib/libcfitsio.a + +ifeq ($(PLATFORM),Darwin) + ifeq ($(PLMACH),x86_64) + CARCH = -m64 -mmacosx-version-min=10.5 + else + CARCH = -arch i386 -m32 -mmacosx-version-min=10.4 + endif + ifdef IRAFARCH + ifeq ($(IRAFARCH),macintel) + CARCH = -m64 -mmacosx-version-min=10.5 + else + CARCH = -arch i386 -m32 -mmacosx-version-min=10.5 + endif + endif +else + CLIBS = $(LIBCURL) -lm -lc -lpthread -lrt + CARCH = + ifeq ($(PLMACH),x86_64) + LFLAGS = -L/usr/lib64 $(LFLAGS) + endif +endif + +#CLIBS = $(LIBCURL) -lm -lpthread -lc +CFLAGS = -g -Wall $(CARCH) -D$(PLATFORM) $(CINCS) -L./ + + + +# list of source and include files + +C_SRCS = votcnv.c votget.c votinfo.c vosesame.c vodata.c voregistry.c \ + votpos.c votcat.c votsplit.c votstat.c votjoin.c voatlas.c \ + votsort.c vosamp.c voiminfo.c \ + voimage.c vocatalog.c vospectra.c votopic.c \ + voApps_spp.c +C_OBJS = votcnv.o votget.o votinfo.o vosesame.o vodata.o voregistry.o \ + votpos.o votcat.o votsplit.o votstat.o votjoin.o voatlas.o \ + votsort.o vosamp.o voiminfo.o \ + voimage.o vocatalog.o vospectra.o votopic.o \ + voApps_spp.o +C_INCS = voApps.h voAppsP.h + + + +F77_SRCS = +F77_OBJS = +F77_INCS = + +SPP_SRCS = +SPP_OBJS = +SPP_INCS = votParse_spp.h + +SPP_TASKS = +F77_TASKS = +C_TASKS = voregistry \ + vosesame \ + vodata voatlas voimage vocatalog vospectra votopic \ + votcnv votget votpos votinfo votstat votsort \ + vosamp \ + voiminfo \ + + # Not yet imlemented (and/or working) + #votcat votsplit votjoin + + +TARGETS = $(F77_TASKS) $(SPP_TASKS) $(C_TASKS) + +SRCS = $(C_SRCS) $(F77_SRCS) $(SPP_SRCS) +OBJS = $(C_OBJS) $(F77_OBJS) $(SPP_OBJS) +HOST_LIBS = $(LIBCURL) $(LFLAGS) -lcfitsio $(CLIBS) +LIBS = lib$(NAME).a -lVOTable -lVOClient -lsamp $(HOST_LIBS) + + + +all: + (make c_progs) + cp lib$(NAME).a $(LIBDIR) + cp $(TARGETS) $(BINDIR) + + +World: lib + +install: all + cp lib$(NAME).a $(LIBDIR) + mv $(TARGETS) $(BINDIR) + +objs: $(OBJS) + + + +# Targets + +#all: $(TARGETS) + +c_progs: $(C_TASKS) +spp_progs: $(SPP_TASKS) +f77_progs: $(F77_TASKS) + +distclean: + make clean + /bin/rm -rf *.fits *.xml + +clean: + /bin/rm -rf .make.state .nse_depinfo *.[aeo] *.dSYM + /bin/rm -rf $(TARGETS) + +everything: + make clean + make all + make install + +help: HELP + +install: all + + + +#################################### +# LIBVOAPPS dependency libraries. +#################################### + +lib: objs suplib + ar rv lib$(NAME).a $(OBJS) + $(RM) $(OBJS) + +suplib: + (cd lib ; make all) + + +############################################################################### +# Unit test programs to be built. +############################################################################### + +demo: $(TARGETS) + +zztest: zztest.c + $(CC) $(CFLAGS) -o zztest zztest.c $(LIBS) + + +########################### +# C Test programs +########################### + +# Note: VOSESSION has its own main() +vosession: vosession.o lib + $(CC) $(CFLAGS) -o vosession vosession.c $(LIBS) + /bin/rm -rf vosession.dSYM + +session_cmd: session_cmd.o lib + $(CC) $(CFLAGS) -o session_cmd session_cmd.c $(LIBS) + /bin/rm -rf session_cmd.dSYM + + +vodata: voApps.c vodata.o lib + $(CC) $(CFLAGS) -o vodata voApps.c $(LIBS) + /bin/rm -rf vodata.dSYM + +voregistry: voApps.c voregistry.o lib + $(CC) $(CFLAGS) -o voregistry voApps.c $(LIBS) + /bin/rm -rf voregistry.dSYM + +vosamp: voApps.c vosamp.o lib + $(CC) $(CFLAGS) -o vosamp voApps.c $(LIBS) + /bin/rm -rf vosamp.dSYM + +voatlas: voApps.c voatlas.o lib + $(CC) $(CFLAGS) -o voatlas voApps.c $(LIBS) + /bin/rm -rf voatlas.dSYM + +voiminfo: voApps.c voiminfo.o lib + $(CC) $(CFLAGS) -o voiminfo voApps.c $(LIBS) + /bin/rm -rf voiminfo.dSYM + +vosloanspec: voApps.c vosloanspec.o lib + $(CC) $(CFLAGS) -o vosloanspec voApps.c $(LIBS) + /bin/rm -rf vosloanspec.dSYM + +votcnv: voApps.c votcnv.o lib + $(CC) $(CFLAGS) -o votcnv voApps.c $(LIBS) + /bin/rm -rf votcnv.dSYM + +votcat: voApps.c votcat.o lib + $(CC) $(CFLAGS) -o votcat voApps.c $(LIBS) + /bin/rm -rf votcat.dSYM + +votget: voApps.c votget.o lib + $(CC) $(CFLAGS) -o votget voApps.c $(LIBS) + /bin/rm -rf votget.dSYM + +votpos: voApps.c votpos.o lib + $(CC) $(CFLAGS) -o votpos voApps.c $(LIBS) + /bin/rm -rf votpos.dSYM + +votinfo: voApps.c votinfo.o lib + $(CC) $(CFLAGS) -o votinfo voApps.c $(LIBS) + /bin/rm -rf votinfo.dSYM + +votjoin: voApps.c votjoin.o lib + $(CC) $(CFLAGS) -o votjoin voApps.c $(LIBS) + /bin/rm -rf votjoin.dSYM + +votsort: voApps.c votsort.o lib + $(CC) $(CFLAGS) -o votsort voApps.c $(LIBS) + /bin/rm -rf votsort.dSYM + +votsplit: voApps.c votsplit.o lib + $(CC) $(CFLAGS) -o votsplit voApps.c $(LIBS) + /bin/rm -rf votsplit.dSYM + +votstat: voApps.c votstat.o lib + $(CC) $(CFLAGS) -o votstat voApps.c $(LIBS) + /bin/rm -rf votstat.dSYM + +vosesame: voApps.c vosesame.o lib + $(CC) $(CFLAGS) -o vosesame voApps.c $(LIBS) + /bin/rm -rf vosesame.dSYM + +voimage: voApps.c voimage.o lib + $(CC) $(CFLAGS) -o voimage voApps.c $(LIBS) + /bin/rm -rf voimage.dSYM + +vocatalog: voApps.c vocatalog.o lib + $(CC) $(CFLAGS) -o vocatalog voApps.c $(LIBS) + /bin/rm -rf vocatalog.dSYM + +vospectra: voApps.c vospectra.o lib + $(CC) $(CFLAGS) -o vospectra voApps.c $(LIBS) + /bin/rm -rf vospectra.dSYM + +votopic: voApps.c votopic.o lib + $(CC) $(CFLAGS) -o votopic voApps.c $(LIBS) + /bin/rm -rf votopic.dSYM + + + +########################### +# SPP Test programs +########################### + + + + +########################### +# Fortran Test programs. +########################### + + + + + + +############################################################################### +# Leave this stuff alone. +############################################################################### + +$(STATICLIB): $(C_SRCS:%.c=Static/%.o) + /usr/bin/ar rv $@ $? +Static/%.o: %.c $(C_INCS) + /usr/bin/gcc $(CINCS) $(CFLAGS) -g -c $< -o $@ +Static: + /bin/mkdir $@ + chmod 777 $@ + +$(SHAREDLIB): $(C_SRCS:%.c=Shared/%.o) + /usr/bin/ld -shared -o $@ $? -lc -ldl +Shared/%.o: %.c $(C_INCS) + /usr/bin/gcc $(CINCS) $(CFLAGS) -fpic -shared -c $< -o $@ +Shared: + /bin/mkdir $@ + chmod 777 $@ diff --git a/vendor/voclient/voapps/README b/vendor/voclient/voapps/README new file mode 100644 index 00000000..aea037b0 --- /dev/null +++ b/vendor/voclient/voapps/README @@ -0,0 +1,324 @@ + +============================= +Last Modified: Aug 10, 2012 +============================= + + + This directory contains the VOClient command-line applications. +Key files in this directory include: + + voApps.c The generic unix main() linked to all tasks + generic.c A template code for building VOClient apps + + voatlas.c The VOATLAS multi-wavelength image atlas task + vodata.c The VODATA general data query retrieval task + + voregistry.c The VOREGISTRY task to query/resolve Registry resources + + vosesame.c The VOSESAME name resolver + + vosamp.c The VOSAMP command-line SAMP tool + + votcnv.c The VOTCNV votable conversion tool + votget.a The VOTGET task to retrieve acrefs from a votable + votinfo.c The VOTINFO task to print information about a votable + votpos.c The VOTPOS task to extract positional cols from votables + votsort.c The VOTSORT task to sort a votable based on a column + votstat.c The VOTSTAT task to print colum statistics + + + Planned tasks Not Yet Implemented: + + votcat.c // VOTable Resource concatenator + votjoin.c // VOTable inner joins + votselect.c // Select rows/cols by index/expr + votsplit.c // Split multi-resource votables + + VOClientd // C-based minimal implementation of VOClient Daeomon + hub // C implementation of SAMP Hub + + voxmatch // Cross-compare local table and VO data + + vosput // Put files to a VOSpace + vosget // Get files from a VOSpace + vosmove // Move files/nodes between VOSpaces + voslist // List files/nodes in a VOSpace + vosdelete // Delete files/nodes in a VOSpace + + voskybot // List known moving objects in an image + + + +The 'lib' subdirectory contains support code for the applications. Of +particular interest is the 'lib/voTask.c' code that defines the tasking +interface used by the applications. + + +Task Interface +-------------- + + All VOClient apps are written as C procedures sharing a common signature: + + <task> (int argc, char **argv, size_t *len, void **result); + +where 'argc' and 'argv' have the usual meaning for the CLI argument vector, +'len' is the length of any returned object (or 0 if there is no return), +and 'result' is a pointer to the returned object in memory. The task() +procedure returns 0 for success, and a positive value to indicate an error +return (this may include a signal number for a crashed child process as +well as task-specific error return codes). + + Tasks share a common main() responsible only for passing in the +parameter options, executing the task as a connected subprocess (or by +calling the procedure directly if the VOAPP_CONNECTED environment variable +is defined, this is to aid in debugging) and for retrieving any returned +result object. This architecture ensures that any memory allocated or +threads spawned by the VOClient app do not interfere with an app using +the language API. + + Host Process App Sub-Process + +----------+ +----------------------+ + | C | parameters | | + | main() |--------------->| VOClient | + | or |<---------------| application code | + | Lang API | result | | + +----------+ +----------------------+ + +The application is spawned as a child process by the main() and the CLI +parameters are sent over IPC. Likewise, any return value from the app is +sent back via IPC, a host CLI tool would simply discard this result however +a language binding or other API would then have a pointer to the result +object it could pass up to the calling interface. The details of what can +be returned by a task is task-specific and the caller must be aware of the +options to be of use, for this discussion the returned 'result' is a memory +object of size 'len' given the above calling signature. + + The 'voApps.c' code contains the common main() function which normally +calls the vo_runTask() procedure to execute the task based on the task name +derived from a lookup table. (See lib/voTask.c for this procedure). + + + +Parameter Interface +------------------- + + VOClient apps are written to accept CLI/parameter options in a number +of formats suited for use as Unix tasks or from an API that may be better +suited to pass in "<param>=<value>" strings. The following formats for +option strings are supported by all tasks: + + -p param[+-] --param --param=value param=<value> + +For CLI tasks the following would be equivalent: + + % task -p # to set the 'p' option + % task --param # long-form of 'p' option + % task --param+ # if 'param' is a boolean option + % task --param=value # to set a specific value for param + % task --param value # to set a specific value for param + % task param=value # to set a specific value for param + +From an API one could imagine these same parameters being passed in to form +the required argument/parameter 'argv' vector as e.g. + + from VOClient import tasks as voc + status = voc.task ("param=value", ....) + +Accomodating a return value from the task would affect this sort of interface +(e.g. if the task were to return an in-memory FITS file instead of a status +code) but the idea is to support both standard CLI options as well as a p=v +format more appropriate for a tasking API interface. + + +Common Options/Parameters: + + All tasks(*) support a core set of options, namely + + -h,--help Print a task usage summary and examples + -%,--test <input> Run unit tests (some tasks require <input>) + -r,--return <opt> Return optional result object + +All other options are task-specific however an effort has been made to make +these consistent across tasks (e.g. a "--input" for input files, "--fmt" for +output VOTable formats, "--samp" for SAMP functionality, etc). + + The "--help" (or "-h") option to each task should provide enough runtime +documentation to get started with using a task, in particular the examples +given in the help are meant to always be valid. + + The "--test" (or "-%") option is a way to run unit tests on a particular +task, primarily based on the examples given in "--help". Depending on the +task an input file/arguments of some form must be provided for the tests to +work. For example, unit tests of VOTable tools can be run using votables +returned from various data services to ensure proper behavior for all VO +resources or to test operation against various (non)compliant files. This +same mechanism can be used to build a regression test suite against a static +list of VO Resources or standardized data files. + + The "--return" option is task-specific and its use will depend largely +on the API implementing it. A detailed description of the return objects +will be provided in the task/API documentation. + + + (*) Exceptions as of this writing are the original VO-CLI tasks + VODATA/VOSESAME/VODIRECTORY, these will be implemented before + release. + + + +SAMP Interoperability +--------------------- + + The VOSAMP task a CLI tool for sending messages to other SAMP-enabled +applications, either as a one-off CLI execution or from within a scripted +environment. To hide the SAMP details, the CLI interface is written to be +more user-friendly, e.g. the options(*) on the command line are (in part): + + + load <url> load the named image/table file + loadImage <url> load the named image + loadVOTable <url> load the named VOTable + loadFITS <url> load the named FITS bintable + showRow [<url>] <row> [tblId] highlight specified row + selectRows [<url>] <rows> [tblId] select specified rows + bibcode <bibcode> load the named bibcode + + exec <cmd> execute a client command + pointAt <ra> <dec> point at given coords + setenv <name> <value> set an environment value + getenv <name> get an environment value + setparam <name> <value> set a parameter value + getparam <name> get a parameter value + + send <mtype> [<args> ...] generalized <mtype> message send + + +where "<url>" might be an actual HTTP reference, a local file path/name, or +a 'file://' URI. The commands themselves are cases insensitive and the +VOSAMP help page should be consulted for details on sending non-standard +messages using the 'send' option for general messages (i.e. those messages +that don't conform to an IVOA-supported 'mtype' but which might be used in +a custom workflow). When VOSAMP is called using an API these commands are +passed through the argument string an provide a trivial high-level method +of sending SAMP messages without requiring the app to explicty connect to +the Hub (receiving messages will still normally require the app to register +itself in order to handle messages using the application's callbacks). + + A "normal" SAMP-enabled application will establish a connection to the +local desktop apps once and then process subsequent messages for the life +of the application. In a CLI tool, this model introduces the overhead of +the initial connection (several seconds) on each command, an effect which +compounds when a CLI tool is used from within a script that might be +processing many tens-to-thousands of messages as it is used in some +user-defined workflow. To avoid this overhead, the VOSAMP task will +default to become a bacakground 'proxy' service that lingers after the +initial command is executed, i.e. in the same way a 'sudo' command won't +require a password for each command for some time after the initial call, +VOSAMP will background itself after the first command to maintain its +connection to SAMP Hub, subsequent calls to VOSAMP will simply forward the +command from the CLI to this proxy to make use of the existing SAMP +connection and execute as quickly as any other persistant SAMP task. + +(*) SSA message data are not yet implemented. + + +Inter-Desktop Messaging: + + VOSAMP reads its command either from stdin, a named command file (e.g. +as from a VOSAMP-shell interpreter), or from a socket created when the proxy +process is created. This socket is created on an inet port that may be +visible to the whole internet, or on a private port restricted by local +system administrators to trusted clients (e.g. port 8080 if that is a +general service provided by a site, or the default port 4000 for sites +willing to open a firewall hole). + + An example sequence of SAMP commands would be something like + + % vosamp listClients + % vosamp loadVOTable foo.xml + +where the first command establishes a SAMP connection, and the second would +forward the CLI command to the (already running) proxy client without +establishing a new-application context. + + In this model, a proxy VOSAMP app reading from an inet socket opens +the possibility of using this proxy from a remote host that can send a +command from a trusted machine. For example, + + On host A: + % vosamp start # start proxy client on host A (140.252.1.86) + + On host B: + % vosamp --proxy=140.252.1.86:4000 loadVOTable foo.xml + +where the '140.252.1.86' is the machine running the intial VOSAMP task, +'4000' is the inet port that proxy is reading commands, and the remainder +of the commandline are args to be passed thru as it they were issued from +the local host. Local data (e.g. the 'foo.xml' file) is sent to the remote +before executing the command, file:// URL's are rewritten so the file +reference remains valid on the remote machine (http:// URLs are unchanged). + + +SAMP Session Manager: (In development) + + By using the proxy client, we can send commands to a VOSAMP application +from a remote machine, but this is not quite the same as federating two (or +more) desktops in a shared session. We are also limited by the ability to +bypass firewalls in order to connect to the proxy client. The solution then +is to have a public "session manager" service that serves as an alternate +input source to the proxy client and will acto to forward message from one +machine to the others. For example, + + +-------------+ + | Session Mgr | + +-------------+ + ^ + / \ + / \ + +-------------------------+ +-------------------------+ + | Topcat \ | | / Topcat | + | Hub - VOSAMP | | VOSAMP - Hub | + | Aladin / | | \ IRAF | + +-------------------------+ +-------------------------+ + Host A Host B + +Since the session manager is on a public host, the VOSAMP on each machine +makes an outgoing client connection and sets up that socket to receive +commands and subscribes to all message types so that SAMP messages received +on the local machine can be forwarded back to the session manager and then +on to other machines in the session. For example, the Aladin on Host A +broadcasts an image.load.FITS message, the VOSAMP on Host forwards the +message to the session manager than then passes it on to the VOSAMP on +Host B for rebroadcast. In this way the message is seen on both desktops +transparently. When local data is being used, this is uploaded to the +session manager for storage in a web-accessible area, the forwarded message +is then rewritten to use the URL and is accessed only when needed. + + Sessions are created/joined with no special setup required, e.g. + + % vosamp --session=foo e.g. commandline tool +or + voc.vosamp ("session=foo") e.g. from language API + +The VOSAMP in this case would contact the session manager to join the list +of machines in session 'foo', this session would be created if it did not +already exist and sessions quietly end when the VOSAMP proxies timeout due +to inactivity or are shut down explicitly. There is no need for formal +security since it is up to the parties in the session to agree on and share +the session name of their choosing. Applications written using the language +bindings can participate in sessions by simply calling the VOSAMP task to +create the proxy regardless of whether it is used explicitly for messaging. + + If the VAO were to operate a public session manager service, it would +trivial to log its use for reporting to the funding agencies, and would +meet the mandate of VAO providing tools for community use. Details of +the communication protocol could be written as an IVOA note to allow other +implementations to make use of the service, or it could be formalized into +a next version of the SAMP protocol itself. + +[Status: Proxy clients for use on the desktop and between trusted machines + is implemented, development of the session manager and extensions to + VOSAMP will be ready for demonstration at the Seattle meeting. (8/11/12)] + + + diff --git a/vendor/voclient/voapps/README.samp b/vendor/voclient/voapps/README.samp new file mode 100644 index 00000000..326eccb0 --- /dev/null +++ b/vendor/voclient/voapps/README.samp @@ -0,0 +1,171 @@ + + +VOSAMP -- SAMP cmdline tool + + + Usage: + + % vosamp [-hvd] [-t to] [-p pattern] [-f file] <cmd> [args ...] + + where <cmd> command to process + -h print help summary + -v verbose output + -d debug output + + -m handle multiple messages + -s <sender> handly only msgs from <sender> + + -t <to> send to specified app (or all) + -p <pattern> message pattern: sync|async|notify + -f <file> send all commands in the file + + Commands: + + snoop print all received messages + send <mtype> [<args> ...] generalized <mtype> message send + + status print Hub availability + list list all registered clients + access <appName> print <appName> availability + handle <mtype> wait for <mtype> message + + exec <cmd> execute a client command + setenv <name> <value> set an environment value + getenv <name> get an environment value + setparam <name> <value> set a parameter value + getparam <name> get a parameter value + + load <url> load the image/table + loadImage <url> load the named image + loadVOTable <url> load the named VOTable + loadFITS <url> load the named FITS bintable + loadSpec <url> load the named spectrum + loadResource <ivorn> load the named VO Resource + + pointAt <ra> <dec> point at given coords + showRow [<url>] [<tblId>] <row> highlight specified row + selectRows [<url>] [<tblId>] <rows> select specified rows + bibcode <bibcode> load the bibcode + + +============================================================================== + + +VOSESSION -- Session manager for inter-desktop messaging + + VOSAMP reads its command either from stdin, a named command file (e.g. +as from a VOSAMP-shell interpreter), or from a socket created when the proxy +process is created. This socket is created on an inet port that may be +visible to the whole internet, or on a private port restricted by local +system administrators to trusted clients (e.g. port 8080 if that is a +general service provided by a site, or the default port 4000 for sites +willing to open a firewall hole). + + An example sequence of SAMP commands would be something like + + % vosamp listClients + % vosamp loadVOTable foo.xml + +where the first command establishes a SAMP connection, and the second would +forward the CLI command to the (already running) proxy client without +establishing a new-application context. + + In this model, a proxy VOSAMP app reading from an inet socket opens +the possibility of using this proxy from a remote host that can send a +command from a trusted machine. For example, + + On host A: + % vosamp start # start proxy client on host A (140.252.1.86) + + On host B: + % vosamp --proxy=140.252.1.86:4000 loadVOTable foo.xml + +where the '140.252.1.86' is the machine running the intial VOSAMP task, +'4000' is the inet port that proxy is reading commands, and the remainder +of the commandline are args to be passed thru as it they were issued from +the local host. Local data (e.g. the 'foo.xml' file) is sent to the remote +before executing the command, file:// URL's are rewritten so the file +reference remains valid on the remote machine (http:// URLs are unchanged). + + +SAMP Session Manager: (In development) + + By using the proxy client, we can send commands to a VOSAMP application +from a remote machine, but this is not quite the same as federating two (or +more) desktops in a shared session. We are also limited by the ability to +bypass firewalls in order to connect to the proxy client. The solution then +is to have a public "session manager" service that serves as an alternate +input source to the proxy client and will acto to forward message from one +machine to the others. For example, + + +-------------+ + | Session Mgr | + +-------------+ + ^ + / \ + / \ + +-------------------------+ +-------------------------+ + | Topcat \ | | / Topcat | + | Hub - VOSAMP | | VOSAMP - Hub | + | Aladin / | | \ IRAF | + +-------------------------+ +-------------------------+ + Host A Host B + +Since the session manager is on a public host, the VOSAMP on each machine +makes an outgoing client connection and sets up that socket to receive +commands and subscribes to all message types so that SAMP messages received +on the local machine can be forwarded back to the session manager and then +on to other machines in the session. For example, the Aladin on Host A +broadcasts an image.load.FITS message, the VOSAMP on Host forwards the +message to the session manager than then passes it on to the VOSAMP on +Host B for rebroadcast. In this way the message is seen on both desktops +transparently. When local data is being used, this is uploaded to the +session manager for storage in a web-accessible area, the forwarded message +is then rewritten to use the URL and is accessed only when needed. + + Sessions are created/joined with no special setup required, e.g. + + % vosamp --session=foo e.g. commandline tool +or + voc.vosamp ("session=foo") e.g. from language API + +The VOSAMP in this case would contact the session manager to join the list +of machines in session 'foo', this session would be created if it did not +already exist and sessions quietly end when the VOSAMP proxies timeout due +to inactivity or are shut down explicitly. There is no need for formal +security since it is up to the parties in the session to agree on and share +the session name of their choosing. Applications written using the language +bindings can participate in sessions by simply calling the VOSAMP task to +create the proxy regardless of whether it is used explicitly for messaging. + + + +============================================================================= + +#define DEF_PORT 4433 /* Session Mgr contact port */ + +#define MAX_SESSIONS 64 /* Max sessions to manage */ +#define MAX_CLIENTS 64 /* Max clients in each session */ + +#define SZ_IPSTR 16 /* Size of an IP string */ + + +typedef struct { + int port; /* connection port */ + char hostIP[SZ_IPSTR]; /* host IP address */ +} Client, *ClientP; + + +typedef struct { + int nclients; /* number of clients */ + Client *clients[MAX_CLIENTS]; /* clients in session */ + char dataCache[SZ_LINE]; /* path to local data cache */ +} Session, *SessionP; + + +#define CALLBACK 0 /* mgr sends callback port */ +#define QUIT 1 /* mgr sends disconnect/client retires */ +#define SEND 2 /* mgr/client forwards cmd */ +#define READY 3 /* mgr ready on port */ + + diff --git a/vendor/voclient/voapps/TODO b/vendor/voclient/voapps/TODO new file mode 100644 index 00000000..d55c3f8c --- /dev/null +++ b/vendor/voclient/voapps/TODO @@ -0,0 +1,4 @@ + + - test cases for all tasks + - VOTINFO should work on multi-RESOURCE VOTables 2/12/13 + - VOTINFO should print <DESCRIPTION> indented properly diff --git a/vendor/voclient/voapps/Tasks b/vendor/voclient/voapps/Tasks new file mode 100644 index 00000000..37c35bb0 --- /dev/null +++ b/vendor/voclient/voapps/Tasks @@ -0,0 +1,59 @@ + + +VO Registry: + voregistry VO Resource discovery + +VO Data Access: + vodata Query and Access VO data + vocatalog Query VO catalog services + voimage Query VO image services +* vospectrum Query VO spectrum services + + voatlas Multi-wavelength atlas images +* voobslog Query public observation logs + vosloanspec SDSS spectral data interface + +VOTable Tools +* votcat Concatenate VOTable into a single multi-resource VOTable + votcnv Convert to/from votable format + votget Download data access references in a VOTable (w/ selection) + votinfo Print information about a votable +* votjoin Perfom an inner-join between two VOTables + votpos Extract positional information from a VOTable +* votselect Select rows from a table + votsort Sort a VOTable by a column +* votsplit Split a multi-resource votable + votstat Compute statistics for numeric columns in a VOTable + +SAMP: + vosamp SAMP utility command (sessions, list clients, start hub, etc) + +Name Resolver: + vosesame Resolve object names to positions + + * Will be in final v1.0 release, probably not in Aug test release + + + +=============================================================================== +== For later versions == +=============================================================================== + +VOClientd C-based minimal implementation of VOClient Daeomon + +SAMP: + hub C implementation of SAMP Hub + samp_proxy Inter-machine SAMP proxy application + +Cross-Compare + voxmatch Cross-compare local table an VO data + +VOSpace: + vosput Put files to a VOSpace + vosget Get files from a VOSpace + vosmove Move files/nodes between VOSpaces + voslist List files/nodes in a VOSpace + vosdelete Delete files/nodes in a VOSpace + +Moving Targets: + skybot List known moving objects in an image diff --git a/vendor/voclient/voapps/_examples b/vendor/voclient/voapps/_examples new file mode 100644 index 00000000..dfffa465 --- /dev/null +++ b/vendor/voclient/voapps/_examples @@ -0,0 +1,41 @@ + +VOSESAME + vosesame m31 # decimal output + vosesame -a m31 # print all info + vosesame -nd m31 # name/decimal + vosesame -dn m31 # decimal/name + +VOREGISTRY + voregistry -r gsc2.3 # resolve serviceURL + voregistry -R hst # expand resolution term + voregistry -t image -b x-ray any # search by constraint + voregistry -t image -b x-ray -v any + voregistry -t image -b x-ray -vv any + + voregistry -list gsc2.3 # list "full" record + voregistry -meta gsc2.3 # list table metadata + + voregistry cooling flow # keyword search + voregistry -vv cooling flow # very-verbose + +VODATA + vodata gsc2.3 ngc1234 # simplest query + vodata gsc2.3 /tmp/_abell.pos # multi-src file input (speed) + vodata -rm 10 gsc2.3 ngc1234 # alt SR spec + vodata -all hst ngc1234 + vodata gsc2.3 ngc1234 + vodata -t image -all hst ngc428 # all HST imgs of obj + # ....use of '-get' + vodata -c -t image noao IC10 # query all image resources + vodata -ep -eu -t image -all hst ngc4258 # ...plus extras + vodata -ep messier m1 180.0 # all-sky, extract pos file + +Combined/Misc + voregistry cooling flow # keyword search + vodata -O white97 -all J/MNRAS/292/419/ # get all tables in paper + + vodata -q -O - http://iraf.net # cat URL + + vodata -cq chandra -i - # interactive use + + diff --git a/vendor/voclient/voapps/_vo-cli.demo b/vendor/voclient/voapps/_vo-cli.demo new file mode 100644 index 00000000..60f19e51 --- /dev/null +++ b/vendor/voclient/voapps/_vo-cli.demo @@ -0,0 +1,44 @@ +VOSESAME + vosesame m31 # decimal output + vosesame -a m31 # print all info + vosesame -nd m31 # name/decimal + vosesame -dn m31 # decimal/name + +VOREGISTRY + voregistry -r gsc2.3 # resolve serviceURL + voregistry -R hst # expand resolution term + voregistry -t image -b x-ray any # search by constraint + voregistry -t image -b x-ray -v any + voregistry -t image -b x-ray -vv any + + voregistry -list gsc2.3 # list "full" record + voregistry -meta gsc2.3 # list table metadata + + voregistry cooling flow # keyword search + voregistry -vv cooling flow # very-verbose + +VODATA + vodata gsc2.3 ngc1234 # simplest query + vodata gsc2.3 /tmp/_abell.pos # multi-src file input (speed) + vodata -rm 10 gsc2.3 ngc1234 # alt SR spec + vodata -all hst ngc1234 + vodata gsc2.3 ngc1234 + vodata -t image -all hst ngc428 # all HST imgs of obj + # ....use of '-get' + vodata -c -t image noao IC10 # query all image resources + vodata -ep -eu -t image -all hst ngc4258 # ...plus extras + vodata -ep messier m1 180.0 # all-sky, extract pos file + +Combined/Misc + voregistry cooling flow # keyword search + vodata -O white97 -all J/MNRAS/292/419/ # get all tables in paper + + vodata -q -O - http://iraf.net # cat URL + + vodata -cq chandra -i - # interactive use + +Web-Page Interface + +GS Demo + + diff --git a/vendor/voclient/voapps/_vo.cap b/vendor/voclient/voapps/_vo.cap new file mode 100644 index 00000000..6e2da272 --- /dev/null +++ b/vendor/voclient/voapps/_vo.cap @@ -0,0 +1,90 @@ + + + We didn't really get to it yesterday, but I wanted to start a +discussion about what specific capabilities we might want to deliver by +June. My understanding is that "immediately useful" has a very high +priority, and a distribution of desktop tools serves a different audience +than an API in any language. + + This set of tools may be packaged and distributed differently +than the API release but offers something people can immediate begin to +play with, rather than tinkering with code to write their own (that will +hopefully come later as well). Also, lots of astronomers will simply want +FITS files or tables to appear to their machine, they may be turned off at +the prospect of walking a votable themselves. + + Given that starting position, I took a look at what's currently +available/possible in VOClient and borrowed some ideas from the IRAF +integration, and came up with about two dozen CLI tools that could +realistically be delivered by a June review (assuming work is split up +between core voclient dev and writing utilities from existing interfaces). +These would be C tools, but the same functionality could be wrapped in +an pythonic interface to provide similar high-level capabilities to +programmers (or simply used to build some other VO tool in python). + + This is just a first cut at such a list, but I think it would be +pretty easy to write user-stories about how having these *capabilities* at +the command-line or scripting environment could be used in a science +workflow. I'd have to think some more about how these fit into the current +ecosystem diagram. Comments? + + +Cheers, +-Mike + +----------- + + +Registry: + vodirectory VO Resource discovery (keyword search, resolution, info) + +Data Access: + vodata Query and Access VO data (general engine) + vocatalog Query VO catalog services (SAMP load to overlay) (1 + voimage Query VO image services (SAMP load to display) (1 + vospectrum Query VO spectrum services (SAMP load) (1 + + dss Load DSS field in display (SAMP to ds9/aladin) (1 + obslog Query public observation logs (1 + + Notes: do we need SED and/or Time Series access tools here? + +VOTable: + votcnv Convert to/from votable format + votget Download data access references in a VOTable (w/ selection) + votsplit Split a multi-resource votable (opt. output conversion) (2a + votjoin Join multiple votables into a multi-resource table (2a + votinfo Print information about a votable + + Notes: similar tools for VOEvent packets could be written + +SAMP: + samp SAMP utility command (list clients, start hub, etc) (2a + send Send a SAMP message from the cmdline (2a + listener Listen for SAMP messages (2a + + Notes: similar tools for VOEvent packets could be written + +Cross-Compare + voxmatch Cross-compare local table an VO data (3 + +VOSpace: + + vosput Put files to a VOSpace (4 + vosget Get files from a VOSpace (4 + vosmove Move files/nodes between VOSpaces (4 + voslist List files/nodes in a VOSpace (4 + vosdelete Delete files/nodes in a VOSpace (4 + +Name Resolver: + sesame Resolve object names to positions + +Moving Targets: + skybot List known moving objects in an image (2b + + + Notes: 1) utility wrapper command around vodata + 2a) exists as simple demo currently and would need work, + 2b) could be written, doesn't currently exist + 3) would require work on SCC progrmmatic interface + 4) would require VOSpace implementation in voclient diff --git a/vendor/voclient/voapps/_z b/vendor/voclient/voapps/_z new file mode 100755 index 00000000..d041968c --- /dev/null +++ b/vendor/voclient/voapps/_z @@ -0,0 +1,13 @@ +#!/bin/csh -fx + +./voatlas -b infrared -o img001.fits ngc4258 +./voatlas -p nvss -v -o img002.fits +./voatlas -s 20m --survey=wise22 -o img003.fits m101 +./voatlas -n 256 --survey=sdssg -o img004.fits ngc4258 +# +./voatlas -n 256 -p sdssg -o img005.fits ngc4258 +# +./voatlas --band=infrared -o img006.fits ngc4258 +./voatlas --survey=nvss -v -o img007.fits +./voatlas --size=20m --survey=wise22 -o img008.fits m101 +./voatlas --naxis=256 --survey=sdssg -o img009.fits ngc4258 diff --git a/vendor/voclient/voapps/data b/vendor/voclient/voapps/data new file mode 120000 index 00000000..92e397c5 --- /dev/null +++ b/vendor/voclient/voapps/data @@ -0,0 +1 @@ +../test-data
\ No newline at end of file diff --git a/vendor/voclient/voapps/f77/README b/vendor/voclient/voapps/f77/README new file mode 100644 index 00000000..0574b098 --- /dev/null +++ b/vendor/voclient/voapps/f77/README @@ -0,0 +1,9 @@ + + This directory contains tasks written or designed for use with +Fortran. In some cases these will simply be example tasks to exercise +or demonstrate the language support. + + +Current Tasks include: + + [None at this time] diff --git a/vendor/voclient/voapps/generic.c b/vendor/voclient/voapps/generic.c new file mode 100644 index 00000000..ddb86adf --- /dev/null +++ b/vendor/voclient/voapps/generic.c @@ -0,0 +1,221 @@ +/* + * GENERIC -- Template file for VOApps task + * + * Usage: + * generic [<otps>] <votable> + * + * @file generic.c + * @author Mike Fitzpatrick + * @date 6/03/12 + * + * @brief Template file for VOApps task. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "votParse.h" /* keep these in order! */ +#include "voApps.h" + + +/* All tasks should support a "--return" flag if they can return a pointer + * to a result as part of the programmatic invocation. As a cmdline task + * 'reslen' and 'result' are ignored (actually, they're thrown away), but + * when called from an API the 'result' is a pointer to an arbitrary memory + * location that is passed back to the caller. + * + * The result object is defined by the task and can be anything. The + * '--return' flag can be defined to take an optional argument to specify + * which of multiple possible objects are returned (e.g. "--return=fits" + * "--return=votable") but the task is responsible for creating the object. + */ +static int do_return = 0; /* return result? */ + +/* Global task declarations. These should all be defined as 'static' to + * avoid namespace collisions. + */ +static int foo = 0; + + +/* A result buffer should be defined to point to the result object if it is + * created dynamically, e.g. a list of votable columns. The task is + * responsible for initially allocating this pointer and then resizing as + * needed. + */ +#define SZ_RESBUF 8192 + +static char *resbuf; + + +/* Task specific option declarations. Task options are declared using the + * getopt_long(3) syntax. + */ +static Task self = { "generic", generic, 0, 0, 0 }; + +static char *opts = "%hno:r"; +static struct option long_opts[] = { + { "test", 2, 0, '%'}, /* --test is std */ + { "help", 2, 0, 'h'}, /* --help is std */ + { "number", 2, 0, 'n'}, /* opt w/ no arg */ + { "output", 1, 0, 'o'}, /* opt w/ required arg */ + { "return", 2, 0, 'r'}, /* --return is std */ + { NULL, 0, 0, 0 } +}; + + +/* All tasks should declare a static Usage() method to print the help + * text in response to a '-h' or '--help' flag. The help text should + * include a usage summary, a description of options, and some examples. + */ +static void Usage (void); +static void Tests (char *input); + + +/** + * Application entry point. All VOApps tasks MUST contain this + * method signature. + */ +int +generic (int argc, char **argv, size_t *reslen, void **result) +{ + /* These declarations are required for the VOApps param interface. + */ + char **pargv, optval[SZ_FNAME]; + + /* These declarations are specific to the task. + */ + char *iname, *oname; + int ch = 0, status = OK, number = 0, pos = 0; + FILE *fd = (FILE *) NULL; + + + /* Initialize result object whether we return an object or not. + */ + *reslen = 0; + *result = NULL; + + /* Initialize local task values. + */ + iname = NULL; + oname = NULL; + + + /* Parse the argument list. The use of vo_paramInit() is required to + * rewrite the argv[] strings in a way vo_paramNext() can be used to + * parse them. The programmatic interface allows "param=value" to + * be passed in, but the getopt_long() interface requires these to + * be written as "--param=value" so they are not confused with + * positional parameters (i.e. any param w/out a leading '-'). + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + while ((ch = vo_paramNext(opts,long_opts,argc,pargv,optval,&pos)) != 0) { + if (ch > 0) { + /* If the 'ch' value is > 0 we are parsing a single letter + * flag as defined in the 'opts string. + */ + switch (ch) { + case '%': Tests (); return (self.nfail); + case 'h': Usage (); return (OK); + case 'n': number++; break; + case 'o': oname = strdup (optval); break; + case 'r': do_return=1; break; + default: + fprintf (stderr, "Invalid option '%s'\n", optval); + return (1); + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + /* This code processes the positional arguments. The 'optval' + * string contains the value but since this string is + * overwritten w/ each arch we need to make a copy (and must + * remember to free it later. + */ + iname = strdup (optval); + break; + } + } + + + /* Sanity checks. Tasks should validate input and accept stdin/stdout + * where it makes sense. + */ + if (iname == NULL) iname = strdup ("stdin"); + if (oname == NULL) oname = strdup ("stdout"); + if (strcmp (iname, "-") == 0) { free (iname), iname = strdup ("stdin"); } + if (strcmp (oname, "-") == 0) { free (oname), oname = strdup ("stdout"); } + + + + /******** + ******** + ******** + ******** + ******** Main body of task + ******** + ******** + ******** + *******/ + + + + + /* Clean up. Rememebr to free whatever pointers were created when + * parsing arguments. + */ + if (iname) + free (iname); + if (oname) + free (oname); + + vo_paramFree (argc, pargv); + + return (status); /* status must be OK or ERR (i.e. 0 or 1) */ +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "generic [<opts>] votable.xml\n\n" + " where\n" + " -%%,--test run unit tests\n" + " -h,--help this message\n" + " -n,--number number output\n" + " -o,--output=<file> output file\n" + " -r,--return return result from method\n" + "\n" + " Examples:\n\n" + " 1) First example\n\n" + " %% generic test.xml\n" + " %% generic -n test.xml\n" + " %% cat test.xml | generic\n" + "\n" + " 2) Second example\n\n" + " %% generic -o pos.txt test.xml\n" + "\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + /* First argument must always be the 'self' variable, the last must + * always be a NULL to terminate the cmd args. + */ + vo_taskTest (self, "--help", NULL); +} + diff --git a/vendor/voclient/voapps/lib/Makefile b/vendor/voclient/voapps/lib/Makefile new file mode 100644 index 00000000..166d64b6 --- /dev/null +++ b/vendor/voclient/voapps/lib/Makefile @@ -0,0 +1,134 @@ +#/////////////////////////////////////////////////////////////////////////////// +#// +#// Makefile for the VOClient Package Applications +#// +#/////////////////////////////////////////////////////////////////////////////// + +# primary dependencies + +NAME = VOApps +VERSION = 1.0 +PLATFORM := $(shell uname -s) +PLMACH := $(shell uname -m) +HERE := $(shell /bin/pwd) +BINDIR := ../../bin/ +LIBDIR := ../../lib/ +INCDIR := ../../include/ + + +# secondary dependencies +LIBBASE = ../lib$(NAME) +STATICLIB = $(HERE)/$(LIBBASE).a +SHAREDLIB = $(HERE)/$(LIBBASE).so.$(VERSION) + + +# stuff that's precious to keep +.PRECIOUS: $(STATICLIB) $(SHAREDLIB) +.KEEP_STATE: + + +# includes, flags and libraries +CC = gcc +CINCS = -I$(HERE) -I../ -I../../include -I../../../../include -L../../lib/ + + +ifeq ($(PLATFORM),Darwin) + ifeq ($(PLMACH),x86_64) + CARCH = -m64 -mmacosx-version-min=10.5 + else + CARCH = -arch i386 -m32 -mmacosx-version-min=10.4 + endif + ifdef IRAFARCH + ifeq ($(IRAFARCH),macintel) + CARCH = -m64 -mmacosx-version-min=10.5 + else + CARCH = -arch i386 -m32 -mmacosx-version-min=10.5 + endif + endif +else + CLIBS = -lm -lc -lcurl -lpthread + CARCH = +endif + +CLIBS = -lm -lc -lcurl -lpthread -lm +CFLAGS = -g -Wall $(CARCH) -D$(PLATFORM) $(CINCS) -L./ + + + + + +# list of source and include files + +SRCS = voObj.c voSvc.c voAclist.c voDALUtil.c voFITS.c voUtil.c \ + voSCS.c voSIAP.c voSSAP.c voUtil.c voRanges.c voLog.c \ + voKML.c voXML.c voHTML.c voTask.c voParams.c vosUtil.c +OBJS = voObj.o voSvc.o voAclist.o voDALUtil.o voFITS.o voUtil.o \ + voSCS.o voSIAP.o voSSAP.o voUtil.o voRanges.o voLog.o \ + voKML.o voXML.o voHTML.o voTask.o voParams.o vosUtil.o +INCS = ../voApps.h ../voAppsP.h + + +all: lib + +install: all + +objs: $(OBJS) + + +# Targets + +clean: + /bin/rm -rf .make.state .nse_depinfo *.[aeo] *.dSYM + /bin/rm -rf $(TARGETS) + +everything: + make clean + make all + make install + +help: HELP + +install: all + + + +#################################### +# LIBVOAPPS dependency libraries. +#################################### + +lib: objs + ar rv ../lib$(NAME).a $(OBJS) + $(RM) $(OBJS) + + + +############################################################################### +# Unit test programs to be built. +############################################################################### + +demo: $(TARGETS) + +zztest: zztest.c + $(CC) $(CFLAGS) -o zztest zztest.c $(LIBS) + + + +############################################################################### +# Leave this stuff alone. +############################################################################### + +$(STATICLIB): $(C_SRCS:%.c=Static/%.o) + /usr/bin/ar rv $@ $? +Static/%.o: %.c $(C_INCS) + /usr/bin/gcc $(CINCS) $(CFLAGS) -c $< -o $@ +Static: + /bin/mkdir $@ + chmod 777 $@ + +$(SHAREDLIB): $(C_SRCS:%.c=Shared/%.o) + /usr/bin/ld -shared -o $@ $? -lc -ldl +Shared/%.o: %.c $(C_INCS) + /usr/bin/gcc $(CINCS) $(CFLAGS) -fpic -shared -c $< -o $@ +Shared: + /bin/mkdir $@ + chmod 777 $@ diff --git a/vendor/voclient/voapps/lib/proto b/vendor/voclient/voapps/lib/proto new file mode 100644 index 00000000..4977acef --- /dev/null +++ b/vendor/voclient/voapps/lib/proto @@ -0,0 +1,236 @@ +/** + * VOAPPPROTO.H -- VOApps prototype headers. + */ + + +/** + * VOACLIST.C -- Procedures for handling the AccessList of images/data + */ +void vot_addToAclist (char *url, char *outfile); +void vot_freeAclist (void); +void vot_procAclist (void); + + +/** + * VODALUTIL.C -- Utility procedures for the DAL interface worker procedures. +*/ +int vot_extractResults (char *result, char delim, svcParams *pars); +char *vot_openExFile (svcParams *pars, int nrows, char *extn, FILE **ofd); +char *vot_getOFName (svcParams *pars, char *extn, int pid); +char *vot_getOFIndex (svcParams *pars, char *extn, int pid); +int vot_countResults (char *result); +void vot_dalExit (int code, int count); +void vot_printHdr (int fd, svcParams *pars); +void vot_printCountHdr (void); +int vot_printCount (Query query, svcParams *pars, int *res_count); +void vot_printCountLine (int nrec, svcParams *pars); + +char vot_svcTypeCode (int type); +char *vot_getExtn (void); + +char *vot_procTimestamp (void); +void vot_concat (void); + + +/** + * VODALUTIL.C -- Utility procedures for the DAL interface worker procedures. + */ +void vot_initHTML (FILE *fd, svcParams *pars); +void vot_printHTMLRow (FILE *fd, char *line, int isHdr, int rownum); +void vot_closeHTML (FILE *fd); + + +/** + * VOINV.C -- VOInventory service routines. + */ +char *vot_doInventory (void); +char *vot_execInv (double ra, double dec, double radius, char *sources, + char *resources, char *id, char *rettype, FILE *outfile); + + +/** + * VOKML.C -- Utility procedures for writing Google KML files. + */ +void vot_initKML (FILE *fd, svcParams *pars); +void vot_printKMLPlacemark (FILE *fd, char *id, double ra, double dec, + char *line, char *acref, svcParams *pars); +void vot_mkPlaceDescr (FILE *fd, char *line, char *acref, svcParams *pars); +void vot_closeKML (FILE *fd); +void vot_concatKML (char *fname); +void vot_concatKMLByObject (FILE *fd); +void vot_concatKMLByService (FILE *fd); +char *vot_getSName (char *root); +char *vot_getOName (char *root); +int vot_copyKMLFile (char *root, char *name, FILE *fd); +void vot_cleanKML (void); + + +/** + * VOLOG.C -- VOApps logging interface. + */ +void vo_appLog (FILE *fd, char *format, ...); +void vo_encodeString (char *buf, char *format, va_list *argp); +char *vo_doarg (va_list **argp, int dtype); +char *vo_logtime (void); + + +/** + * VOARGS.C -- Procedures for commandline argument handling. We also do + */ +int vot_parseObjectList (char *list, int isCmdLine); +void vot_freeObjectList (void); +int vot_countObjectList (void); +int vot_printObjectList (FILE *fd); +void vot_readObjFile (char *fname); + + +/** + * VOPARAMS.C -- Interface to manage cmdline options or library parameters. + */ +char **vo_paramInit (int argc, char *argv[]); +int vo_paramNext (char *opts, struct option long_opts[], int argc, + char *argv[], char *optval, int *posindex); +void vo_paramFree (int argc, char *argv[]); + + +/** + * VORANGES -- Simple range-specification package to decode lists of numbers + * or ranges of the form: + */ +int vot_decodeRanges (range_string, ranges, max_ranges, nvalues); +int get_next_number (int ranges[], int number); +int is_in_range (int ranges[], int number); + + +/** + * VOSCS.C -- Worker procedure to query a Simple Cone Search service. + */ +int vot_callConeSvc (svcParams *pars); + + +/** + * VOSIAP.C -- Worker procedure to make a query to an SIAP service. + */ +int vot_callSiapSvc (svcParams *pars); +char *vot_validateFile (char *fname); + + +/** + * VOSSAP.C -- Worker procedure to make a query to an SSAP service. + */ +int vot_callSsapSvc (svcParams *pars); + + +/** + * VOSVC.C -- Procedures for commandline argument and DAL service handling. + */ +int vot_parseServiceList (char *list, int dalOnly); +void vot_freeServiceList (void); +void vot_resetServiceCounters (void); +void vot_addToSvcList (char *name, char *ident, char *url, char *type, + char *title); +int vot_countServiceList (void); +int vot_printServiceList (FILE *fd); +int vot_printServiceVOTable (FILE *fd); +void vot_readSvcFile (char *fname, int dalOnly); + + +/** + * VOTASK.C -- Utilities to run a VOApps task as a connected subprocess. + */ +int vo_runTask (char *method, Task *apps, int argc, char **argv, size_t *len, + void **result); +int vo_taskTest (Task self, char *arg, ...); + +int vo_setResultFromFile (char *fname, size_t *len, void **data); +int vo_setResultFromInt (int value, size_t *len, void **data); +int vo_setResultFromReal (float value, size_t *len, void **data); +int vo_setResultFromString (char *str, size_t *len, void **data); + + +/** + * VOUTIL.C -- Utility procedures for the VO-CLI tasks. + */ +int vot_regResolver (char *term, char *svctype, char *bpass, char *subject, + char *fields, int index, int exact, int dalOnly, char **res); +int vot_regSearch (char **ids, int nids, char *svctype, char *bpass, + char *subject, int orValues, int votable, int dalOnly, + int sortRes, int terse); +void pretty_print (char *result, int nresults); + +void ppResSummary (char *result, int nresults); +void ppMultiLine (char *result, int poffset, int pwidth, int maxchars); + +void pretty_print_table (char *result, int nresults, char *fields); +char *vot_parseSvcType (char *svctype, int exact); + +char *vot_parseBandpass (char *bpass); +char *vot_parseSubject (char *subject); + +char *vot_urlFname (char *url); +void vot_printAttrs (char *fname, Query query, char *ident); +void vot_printRegVOTableHdr (FILE *fd); + +void vot_printRegVOTableRec (FILE *fd, RegResult resource, int recnum); +void vot_printRegVOTableTail (FILE *fd); + +char *xmlEncode (char *in); +char *vot_getline (FILE *fd); +char *vot_normalizeCoord (char *coord); +char *vot_normalize (char *str); + +int isVOTable (char *fname); /* utility functions */ +int isSexagesimal (char *str); +int isDecimal (char *str); +float sexa (char *s); +char *toSexa (double pos); +char *toSexaTime (int nsec); +char *vot_mktemp (char *root); +char *vot_copyStdin (void); +void vot_skipHdr (FILE *fd); + +char *vot_getTableCol (char *line, int col, int span); +int vot_isNumericField (handle_t field); +int vot_fileType (char *fname); +int vot_sum32 (char *str); +int strdic (char *in_str, char *out_str, int maxchars, char *dict); + + +/** +** VOXML.C -- Utility procedures for writing XML files, i.e. the raw +*/ + +void vot_concatXML (char *fname); +int vot_copyXMLFile (char *root, char *name, FILE *fd); +void vot_cleanXML (void); + + +/** + * VOSUTIL.C - Utility routines for the VOSAMP tools. + */ +int vos_urlType (char *url); +char *vos_getFName (char *path); +char *vos_typeName (int type); +int vos_getURL (char *url, char *fname); +char *vos_optArg (char *arg); +char *vos_toURL (char *arg); +int *vos_toIntArray (char *arg, int *nrows); + +int vos_openServerSocket (int port); +int vos_openClientSocket (char *host, int port, int retry); +int vos_testClientSocket (char *host, int port); +int vos_sockReadHdr (int fd, int *len, char *name, int *type, int *mode); +int vos_sockWriteHdr (int fd, int len, char *name, int type, int mode, + char *to); +void vos_sockPrintHdr (char *msg, int fd); +int vos_sockRead (int fd, void *vptr, int nbytes); +int vos_sockWrite (int fd, void *vptr, int nbytes); +int vos_fileRead (int fd, void *vptr, int nbytes); +int vos_fileWrite (int fd, void *vptr, int nbytes); +void vos_setNonBlock (int sock); +char *vos_getLocalIP (void); + +struct hostent *vos_getHostByName (char *name); +struct hostent *vos_dupHostent (struct hostent *hentry); + +int vos_strsub (char *in, char *from, char *to, char *outstr, int maxch); diff --git a/vendor/voclient/voapps/lib/voAclist.c b/vendor/voclient/voapps/lib/voAclist.c new file mode 100644 index 00000000..de63c6f8 --- /dev/null +++ b/vendor/voclient/voapps/lib/voAclist.c @@ -0,0 +1,299 @@ +/************************************************************************ +** VOACLIST.C -- Procedures for handling the AccessList of images/data +** to be downloaded. +** +** M. Fitzpatrick, NOAO, July 2007 +*/ + +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include "VOClient.h" +#include "voAppsP.h" + + +/* Local processing definitions. +*/ + +extern Acref *acList, *acTail; /* Access reference linked list */ +extern int nacrefs; /* number of access refs */ +extern int file_get; /* number of files to get */ +extern time_t as_time, ae_time; /* processing times */ + +extern int debug, verbose, quiet; +extern int max_download; +extern char *output; +extern int errno; /* system error code */ + +extern Range fileRange; /* download file range list */ + +extern char *vot_validateFile (char *fname); +extern char *vot_urlFname (char *url); + + +/* Local task prototypes. +*/ +void vot_addToAclist (char *url, char *fname); +void vot_freeAclist (void); +void vot_procAclist (void); + +static pid_t vot_dlProc (Acref *ac, int filenum); +static int vot_acGetURL (char *url, char *fname, long *size); + + + +/************************************************************************ +** VOT_ADDTOACLIST -- Add the given url/id to the file access list. +*/ +void +vot_addToAclist (char *url, char *outfile) +{ + Acref *new = calloc (1, sizeof (Acref)); + + bzero (new->url, SZ_LINE); + bzero (new->fname, SZ_FNAME); + + strncpy (new->url, url, strlen (url)); + if (outfile) + strncpy (new->fname, outfile, strlen (outfile)); + new->index = nacrefs; + + new->status = AC_PENDING; + if (!acList) { + acList = acTail = new; + + } else { + acTail->next = new; + acTail = new; + } + nacrefs++; +} + + +/************************************************************************ +** VOT_FREEACLIST -- Free the Aclist structure and reset the counter. +*/ +void +vot_freeAclist () +{ + register int i; + Acref *cur, *next; + + + cur = acList; + for (i=0; i < nacrefs; i++) { + next = cur->next; + if (cur) + free ((void *)cur); + cur = next; + } + + nacrefs = 0; + acList = acTail = (Acref *) NULL; +} + + +/************************************************************************ +** VOT_PROCACLIST -- Begin processing the access list. We do this by +** spawning up to MAX_DOWNLOADS procs to download the references in +** parallel. +*/ +void +vot_procAclist (void) +{ + int nthreads, nfile, nrunning, nremaining; + pid_t pid, rc, status; + Acref *ac = acList; + + + /* Initialize. + */ + nthreads = (nacrefs > max_download) ? max_download : nacrefs; + nrunning = 0; + nremaining = nacrefs; + + as_time = time ((time_t) NULL); /* get start time */ + + + if (verbose && !quiet) + printf ("\n# Beginning download of %d files....\n", nacrefs); + + for (nfile=1; nremaining > 0;) { + + /* Spawn a process thread for each access reference. + */ + if (nrunning < nthreads && nfile <= nacrefs) { + + if (debug) + fprintf (stderr, "Starting download for '%s'\n", ac->url); + + if ((pid = vot_dlProc (ac, nfile)) < 0) { + fprintf (stderr, "ERROR: process fork() fails\n"); + exit (-1); + } + nrunning++; + nfile++; + + if (ac) + ac = ac->next; + + } else { + /* All processes running, wait for one to finish. + */ + if (debug) + fprintf (stderr, "Waiting on download\n"); + + if ((rc = waitpid ((pid_t)-1, &status, (int) 0)) < 0) { + fprintf (stderr, "ERROR: aclist waitpid() fails, code: %d\n", + (int)rc); + exit (-1); + } + status = WEXITSTATUS(status); + + nrunning--; + nremaining--; + } + } + + if (verbose && !quiet) + printf ("#\n# Downloads complete.\n"); + + + ae_time = time ((time_t) NULL); /* get end time */ + + return; +} + + +/************************************************************************ +** VOT_DLPROC -- Procedure used to spawn a download child process. We +** return the child pid, and fork off the actual download. The caller +** will wait for completion. +*/ +static pid_t +vot_dlProc (Acref *ac, int filenum) +{ + pid_t cpid; + int nerrs = 0; + long nbytes = 0; + char *urlFname, *out, svc[SZ_FNAME], idx[10], fname[SZ_FNAME]; + + + if (debug) + fprintf (stderr, "vot_dlProc(%d): %s\n", filenum, ac->url); + + if ((cpid = fork()) < 0) { + fprintf (stderr, + "vot_dlProc: Unable to create child process, exiting\n"); + exit (-1); + + } else if (cpid > 0) { + return (cpid); /* parent */ + + } else { /* child */ + /* Initialize the VOClient code. Error messages are printed by the + ** interface so we just quit if there is a problem. + */ + if (voc_initVOClient ((char *) NULL) == ERR) + exit (1); + + bzero (idx, 10); + bzero (svc, SZ_FNAME); + if (ac->fname[0]) { + char *ip, *op; + + strcpy (fname, ac->fname); + for (ip=fname,op=svc; *ip && *ip != '.'; ) + *op++ = *ip++; + ip++; + if (isdigit(*ip)) + strcpy (idx, ip); + else + strcpy (idx, "001"); + } else { + bzero (fname, SZ_FNAME); + sprintf (fname, "%s%03d", (output ? output : "file"), filenum); + strcpy (svc, "file"); + sprintf (idx, "%03d", filenum); + } + + urlFname = vot_urlFname(ac->url); + if (verbose) { + if (strcmp (idx, "001") == 0 && !quiet) + fprintf (stderr, "#\n# Downloading URLs from service: %s...\n", + svc); + if (!quiet) + fprintf (stderr, "# File %s...", idx); + } + + nerrs = vot_acGetURL (ac->url, fname, &nbytes); + + out = vot_validateFile (fname); + + if (verbose && !quiet && !nerrs) + fprintf (stderr, " (%ld bytes) file: %s\n", nbytes, out); + + strcpy (ac->fname, fname); + ac->nbytes = nbytes; + ac->status = (nerrs ? AC_ERROR : AC_COMPLETE); + + voc_closeVOClient (0); /* close VOClient connection */ + } + + exit (0); +} + + +/************************************************************************ +** Download a raw URL to the named file. +*/ + +static int +vot_acGetURL (char *url, char *fname, long *size) +{ + int fd, nbytes, err = 0; + char *res; + extern char *output; + + + if ((res = voc_getRawURL (url, &nbytes)) == NULL) { + fprintf (stderr, "Cannot access URL\n"); + err++; + } else { + if (output && output[0] == '-') /* use stdout */ + fd = fileno(stdout); + else { + if (access (fname, R_OK|W_OK) == 0) /* overwrite */ + unlink (fname); + + /* Open the file. + */ + if ((fd = open (fname, O_RDWR|O_CREAT, 0644)) < 0) { + fprintf (stderr, "Cannot open file '%s'\n", + fname); + err++; + } + } + + /* Write the (binary) result string to the file. + */ + if (write (fd, res, nbytes) != nbytes) { + fprintf (stderr, "Short file write\n"); + err++; + } + + if (fd != fileno(stdout)) /* close if not stdout */ + close (fd); + } + + if (res) + free ((char *) res); + + *size = nbytes; /* return the size */ + return (err); +} diff --git a/vendor/voclient/voapps/lib/voAppProto.h b/vendor/voclient/voapps/lib/voAppProto.h new file mode 100644 index 00000000..7114afda --- /dev/null +++ b/vendor/voclient/voapps/lib/voAppProto.h @@ -0,0 +1,238 @@ +/** + * VOAPPPROTO.H -- VOApps prototype headers. + */ + + +/** + * VOACLIST.C -- Procedures for handling the AccessList of images/data + */ +void vot_addToAclist (char *url, char *outfile); +void vot_freeAclist (void); +void vot_procAclist (void); + + +/** + * VODALUTIL.C -- Utility procedures for the DAL interface worker procedures. +*/ +int vot_extractResults (char *result, char delim, svcParams *pars); +char *vot_openExFile (svcParams *pars, int nrows, char *extn, FILE **ofd); +char *vot_getOFName (svcParams *pars, char *extn, int pid); +char *vot_getOFIndex (svcParams *pars, char *extn, int pid); +int vot_countResults (char *result); +void vot_dalExit (int code, int count); +void vot_printHdr (int fd, svcParams *pars); +void vot_printCountHdr (void); +int vot_printCount (Query query, svcParams *pars, int *res_count); +void vot_printCountLine (int nrec, svcParams *pars); + +char vot_svcTypeCode (int type); +char *vot_getExtn (void); + +char *vot_procTimestamp (void); +void vot_concat (void); + + +/** + * VODALUTIL.C -- Utility procedures for the DAL interface worker procedures. + */ +void vot_initHTML (FILE *fd, svcParams *pars); +void vot_printHTMLRow (FILE *fd, char *line, int isHdr, int rownum); +void vot_closeHTML (FILE *fd); + + +/** + * VOINV.C -- VOInventory service routines. + */ +char *vot_doInventory (void); +char *vot_execInv (double ra, double dec, double radius, char *sources, + char *resources, char *id, char *rettype, FILE *outfile); + + +/** + * VOKML.C -- Utility procedures for writing Google KML files. + */ +void vot_initKML (FILE *fd, svcParams *pars); +void vot_printKMLPlacemark (FILE *fd, char *id, double ra, double dec, + char *line, char *acref, svcParams *pars); +void vot_mkPlaceDescr (FILE *fd, char *line, char *acref, svcParams *pars); +void vot_closeKML (FILE *fd); +void vot_concatKML (char *fname); +void vot_concatKMLByObject (FILE *fd); +void vot_concatKMLByService (FILE *fd); +char *vot_getSName (char *root); +char *vot_getOName (char *root); +int vot_copyKMLFile (char *root, char *name, FILE *fd); +void vot_cleanKML (void); + + +/** + * VOLOG.C -- VOApps logging interface. + */ +void vo_appLog (FILE *fd, char *format, ...); +void vo_encodeString (char *buf, char *format, va_list *argp); +char *vo_doarg (va_list **argp, int dtype); +char *vo_logtime (void); + + +/** + * VOARGS.C -- Procedures for commandline argument handling. We also do + */ +int vot_parseObjectList (char *list, int isCmdLine); +void vot_freeObjectList (void); +int vot_countObjectList (void); +int vot_printObjectList (FILE *fd); +void vot_readObjFile (char *fname); + + +/** + * VOPARAMS.C -- Interface to manage cmdline options or library parameters. + */ +char **vo_paramInit (int argc, char *argv[]); +int vo_paramNext (char *opts, struct option long_opts[], int argc, + char *argv[], char *optval, int *posindex); +void vo_paramFree (int argc, char *argv[]); + + +/** + * VORANGES -- Simple range-specification package to decode lists of numbers + * or ranges of the form: + */ +int vot_decodeRanges (range_string, ranges, max_ranges, nvalues); +int get_next_number (int ranges[], int number); +int is_in_range (int ranges[], int number); + + +/** + * VOSCS.C -- Worker procedure to query a Simple Cone Search service. + */ +int vot_callConeSvc (svcParams *pars); + + +/** + * VOSIAP.C -- Worker procedure to make a query to an SIAP service. + */ +int vot_callSiapSvc (svcParams *pars); +char *vot_validateFile (char *fname); + + +/** + * VOSSAP.C -- Worker procedure to make a query to an SSAP service. + */ +int vot_callSsapSvc (svcParams *pars); + + +/** + * VOSVC.C -- Procedures for commandline argument and DAL service handling. + */ +int vot_parseServiceList (char *list, int dalOnly); +void vot_freeServiceList (void); +void vot_resetServiceCounters (void); +void vot_addToSvcList (char *name, char *ident, char *url, char *type, + char *title); +int vot_countServiceList (void); +int vot_printServiceList (FILE *fd); +int vot_printServiceVOTable (FILE *fd); +void vot_readSvcFile (char *fname, int dalOnly); + + +/** + * VOTASK.C -- Utilities to run a VOApps task as a connected subprocess. + */ +int vo_runTask (char *method, Task *apps, int argc, char **argv, size_t *len, + void **result); +int vo_taskTest (Task self, char *arg, ...); + +int vo_setResultFromFile (char *fname, size_t *len, void **data); +int vo_setResultFromInt (int value, size_t *len, void **data); +int vo_setResultFromReal (float value, size_t *len, void **data); +int vo_setResultFromString (char *str, size_t *len, void **data); + + +/** + * VOUTIL.C -- Utility procedures for the VO-CLI tasks. + */ +int vot_regResolver (char *term, char *svctype, char *bpass, char *subject, + char *fields, int index, int exact, int dalOnly, char **res); +int vot_regSearch (char **ids, int nids, char *svctype, char *bpass, + char *subject, int orValues, int votable, FILE *vot_fd, + int dalOnly, int sortRes, int terse); +void pretty_print (char *result, int nresults); + +void ppResSummary (char *result, int nresults); +void ppMultiLine (char *result, int poffset, int pwidth, int maxchars); + +void pretty_print_table (char *result, int nresults, char *fields); +char *vot_parseSvcType (char *svctype, int exact); + +char *vot_parseBandpass (char *bpass); +char *vot_parseSubject (char *subject); + +char *vot_urlFname (char *url); +void vot_printAttrs (char *fname, Query query, char *ident); +void vot_printRegVOTableHdr (FILE *fd); + +void vot_printRegVOTableRec (FILE *fd, RegResult resource, int recnum); +void vot_printRegVOTableTail (FILE *fd); + +char *xmlEncode (char *in); +char *vot_getline (FILE *fd); +char *vot_normalizeCoord (char *coord); +char *vot_normalize (char *str); +char *vot_toURL (char *arg); +void vot_setArg (char **argv, int *argc, char *value); + +int isVOTable (char *fname); /* utility functions */ +int isSexagesimal (char *str); +int isDecimal (char *str); +float sexa (char *s); +char *toSexa (double pos); +char *toSexaTime (int nsec); +char *vot_mktemp (char *root); +char *vot_copyStdin (void); +void vot_skipHdr (FILE *fd); + +char *vot_getTableCol (char *line, int col, int span); +int vot_isNumericField (handle_t field); +int vot_fileType (char *fname); +int vot_sum32 (char *str); +int strdic (char *in_str, char *out_str, int maxchars, char *dict); + + +/** +** VOXML.C -- Utility procedures for writing XML files, i.e. the raw +*/ + +void vot_concatXML (char *fname); +int vot_copyXMLFile (char *root, char *name, FILE *fd); +void vot_cleanXML (void); + + +/** + * VOSUTIL.C - Utility routines for the VOSAMP tools. + */ +int vos_urlType (char *url); +char *vos_getFName (char *path); +char *vos_typeName (int type); +int vos_getURL (char *url, char *fname); +char *vos_optArg (char *arg); +char *vos_toURL (char *arg); +int *vos_toIntArray (char *arg, int *nrows); + +int vos_openServerSocket (int port); +int vos_openClientSocket (char *host, int port, int retry); +int vos_testClientSocket (char *host, int port); +int vos_sockReadHdr (int fd, int *len, char *name, int *type, int *mode); +int vos_sockWriteHdr (int fd, int len, char *name, int type, int mode, + char *to); +void vos_sockPrintHdr (char *msg, int fd); +int vos_sockRead (int fd, void *vptr, int nbytes); +int vos_sockWrite (int fd, void *vptr, int nbytes); +int vos_fileRead (int fd, void *vptr, int nbytes); +int vos_fileWrite (int fd, void *vptr, int nbytes); +void vos_setNonBlock (int sock); +char *vos_getLocalIP (void); + +struct hostent *vos_getHostByName (char *name); +struct hostent *vos_dupHostent (struct hostent *hentry); + +int vos_strsub (char *in, char *from, char *to, char *outstr, int maxch); diff --git a/vendor/voclient/voapps/lib/voApps_f77.c b/vendor/voclient/voapps/lib/voApps_f77.c new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/vendor/voclient/voapps/lib/voApps_f77.c diff --git a/vendor/voclient/voapps/lib/voApps_spp.c b/vendor/voclient/voapps/lib/voApps_spp.c new file mode 100644 index 00000000..568cd97f --- /dev/null +++ b/vendor/voclient/voapps/lib/voApps_spp.c @@ -0,0 +1,271 @@ +/** + * VOTAPP_SPP.C -- SPP Interface routines to applications code. + * + * @file votApp_spp.c + * @author Mike Fitzpatrick + * @date 6/03/11 + * + * @brief SPP Interface routines to applications code. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <unistd.h> +#include <ctype.h> +#include <errno.h> + +/* +#include "votParseP.h" +*/ +#include "votParse.h" + + +/* SPP Type definitions. +*/ +#define XCHAR short +#define PKCHAR char +#define XINT int +#define XEOS 0 + + +/* SPP Interface Definitions. + * + * SPP compilers on various platforms may append one or more trailing + * underscores to symbol names, we'll use macros for the interface names + * and use defines to see what the symbol name is. +*/ +#ifdef _NO_US_ + +#define VX_VODATA vxvoda +#define VX_VODIRECTORY vxvody +#define VX_VODSS vxvods +#define VX_VOSESAME vxvose + +#define VX_VOCOPY vxvocy +#define VX_VOGET vxvogt +#define VX_VOINFO vxvoio + +#else + +#define VX_VODATA vxvoda_ +#define VX_VODIRECTORY vxvody_ +#define VX_VODSS vxvods_ +#define VX_VOSESAME vxvose_ + +#define VX_VOCOPY vxvocy_ +#define VX_VOGET vxvogt_ +#define VX_VOINFO vxvoio_ + +#endif + +typedef void (*PFV)(); +typedef int (*PFI)(); + + + +/** + * Local interface declarations. + */ +static PKCHAR *spp2c (XCHAR *instr, int maxch); +static int spplen (XCHAR *str); +static void func_exec (PFV func, char *name, int *argc, XCHAR *firstArg, + va_list argp); + + + +/***************************************************************************** + * Application Interfaces + ****************************************************************************/ + +#define MAX_ARGS 64 + +void vodata (int argc, char **argv); +void vodirectory (int argc, char **argv); +void vodss (int argc, char **argv); +void vosesame (int argc, char **argv); + +void votcopy (int argc, char **argv); +void votget (int argc, char **argv); +void votinfo (int argc, char **argv); + +void voc_debug (void); + + + +/** + * FUNC_EXEC -- Execute a VOClient function from the SPP binding. + */ +static void +func_exec (PFV func, char *name, int *argc, XCHAR *firstArg, va_list argp) +{ + int i, _argc = *argc; + char *_argv[MAX_ARGS]; + XCHAR *arg; + + if (firstArg == NULL) /* must pass in at least one arg */ + return; + + + /* Process the argument list. + */ + _argc = *argc + 1; + _argv[0] = strdup (name); + _argv[1] = spp2c (firstArg, spplen (firstArg)); + + for (i=2; i < _argc && (arg=(XCHAR *)va_arg(argp,XCHAR *)) != NULL; i++) + if (arg) + _argv[i] = spp2c (arg, spplen (arg)); + + /* Debug output. + */ + if (access ("/tmp/VOC_DEBUG", F_OK) == 0) { + for (i=0; i < _argc; i++) + fprintf (stderr, "%s ", _argv[i]); + fprintf (stderr, "\n"); + } + + + (*func) (_argc, _argv); /* call the task */ + + for (i=0; i < *argc; i++) /* free the arg pointers */ + if (_argv[i]) + free ((char *) _argv[i]); + + return; +} + + +/**************************************************************************** + * Task wrappers + ****************************************************************************/ + +/** + * VX_VOCOPY -- Application interface to the VOCOPY task. + */ +void VX_VOCOPY (int *argc, XCHAR *firstArg, ...) +{ + va_list argp; + + va_start (argp, firstArg); + func_exec (votcopy, "votcopy", argc, firstArg, argp); + va_end (argp); +} + + +/** + * VX_VODATA -- Application interface to the VODATA task. + */ +void VX_VODATA (int *argc, XCHAR *firstArg, ...) +{ + va_list argp; + + va_start (argp, firstArg); + func_exec (vodata, "vodata", argc, firstArg, argp); + va_end (argp); +} + + +/** + * VX_VODIRECTORY -- Application interface to the VODIRECTORY task. + */ +void VX_VODIRECTORY (int *argc, XCHAR *firstArg, ...) +{ + va_list argp; + + va_start (argp, firstArg); + func_exec (vodirectory, "vodirectory", argc, firstArg, argp); + va_end (argp); +} + + +/** + * VX_VODSS -- Application interface to the VODSS task. + */ +void VX_VODSS (int *argc, XCHAR *firstArg, ...) +{ + va_list argp; + + va_start (argp, firstArg); + func_exec (vodss, "vodss", argc, firstArg, argp); + va_end (argp); +} + + +/** + * VX_VOGET -- Application interface to the VOGET task. + */ +void VX_VOGET (int *argc, XCHAR *firstArg, ...) +{ + va_list argp; + + va_start (argp, firstArg); + func_exec (votget, "votget", argc, firstArg, argp); + va_end (argp); +} + +/** + * VX_VOINFO -- Application interface to the VOTINFO task. + */ +void VX_VOINFO (int *argc, XCHAR *firstArg, ...) +{ + va_list argp; + + va_start (argp, firstArg); + func_exec (votinfo, "votinfo", argc, firstArg, argp); + va_end (argp); +} + + +/** + * VX_VOSESAME -- Application interface to the VOSESAME task. + */ +void VX_VOSESAME (int *argc, XCHAR *firstArg, ...) +{ + va_list argp; + + va_start (argp, firstArg); + func_exec (vosesame, "vosesame", argc, firstArg, argp); + va_end (argp); +} + + + +/**************************************************************************** + * Private utility procedures + ****************************************************************************/ + +/** + * SPP2C -- Convert an SPP string to a host C string. + */ +static char * +spp2c (XCHAR *instr, int maxch) +{ + XCHAR *ip = instr; + char *outstr = (char *) calloc (1, maxch+1); + char *op = (char *) outstr; + int n = maxch; + + while ((*op++ = (char)*ip++) != (char)XEOS && --n >= 0) + ; + *--op = (char) XEOS; + + return (outstr); +} + + +/** + * SPPLEN -- Get the length of an SPP string. + */ +static int +spplen (XCHAR *str) +{ + int len = 0; + + for (len=0; str[len] != (XCHAR) XEOS; len++) + ; + return (len); +} + +void voc_debug () { int junk; junk = 1; } diff --git a/vendor/voclient/voapps/lib/voDALUtil.c b/vendor/voclient/voapps/lib/voDALUtil.c new file mode 100644 index 00000000..f02ffda1 --- /dev/null +++ b/vendor/voclient/voapps/lib/voDALUtil.c @@ -0,0 +1,839 @@ +/************************************************************************ +** VODALUTIL.C -- Utility procedures for the DAL interface worker +** procedures. +** +** M. Fitzpatrick, NOAO, July 2007 +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include <time.h> +#include <pthread.h> +#include "VOClient.h" +#include "voAppsP.h" + + +extern int errno, nservices, nobjects, quiet, format, simple_out, numout; +extern int debug, verbose, all_named, all_data, save_res, extract; +extern int meta, dverbose, count, count_only, file_get, use_name; +extern int kml_max, kml_sample, kml_region, kml_label; +extern char *output; + +extern Service *svcList; +extern Object *objList; + +extern char *vot_getSName (char *root); +extern char *vot_getOName (char *root); + + + +int vot_extractResults (char *result, char delim, svcParams *pars); +int vot_printCount (Query query, svcParams *pars, int *count); +char vot_svcTypeCode (int type); +char *vot_getOFName (svcParams *pars, char *extn, int pid); +char *vot_getOFIndex (svcParams *pars, char *extn, int pid); +char *vot_openExFile (svcParams *pars, int nrows, char *extn, FILE **ofd); +char *vot_procTimestamp (void); +char *vot_getExtn (void); +void vot_printCountHdr (void); +void vot_printCountLine (int nrec, svcParams *pars); +void vot_dalExit (int code, int count); +void vot_printHdr (int fd, svcParams *pars); +void vot_concat (); + +static void vot_clean (char *extn); +static int vot_copyFile (char *root, char *extn, char *name, + FILE *fd, int hdr, int nrows); + +extern char *vot_normalize (char *str); +extern char *vot_normalizeCoord (char *str); + +extern void vot_initKML (FILE *fd, svcParams *pars); +extern void vot_printKMLPlacemark (FILE *fd, char *id, + double ra, double dec, char *line, char *acref, + svcParams *pars); +extern void vot_closeKML (FILE *fd); + +extern void vot_initHTML (FILE *fd, svcParams *pars); +extern void vot_printHTMLRow (FILE *fd, char *line, int isHdr, int rnum); +extern void vot_closeHTML (FILE *fd); + + + + + +/************************************************************************ +** VOC_EXTRACTRESULTS -- Extract the position and acref information from +** a DAL query result. We use the first occurance of the POS_EQ_MAIN_<t> +** UCDs for the position and either ID_MAIN or an artificial ID. Format +** for the position file is fixed but may be generalized later to allow +** the order/delimiter to be controlled by the user. The acref file +** contains the contents of the VOX:Image_AccessReference element. +*/ +int +vot_extractResults (char *result, char delim, svcParams *pars) +{ + int id=-1, ra=-1, dec=-1, acref=-1, colnum, rownum, nrows, ncols, np, na; + char col[SZ_LINE], s_id[SZ_LINE], s_ra[SZ_LINE], s_dec[SZ_LINE]; + char s_acref[SZ_URL], afname[SZ_LINE], pfname[SZ_LINE]; + char hfname[SZ_LINE], kfname[SZ_LINE]; + char *ip = result, *sres, *op, *lp; + char hline[SZ_RESULT], line[SZ_RESULT]; + FILE *pfd = (FILE *)NULL; + FILE *afd = (FILE *)NULL; + FILE *kfd = (FILE *)NULL; + FILE *hfd = (FILE *)NULL; + + static int row_count = 0; + + + if (!result) + vot_dalExit (E_NODATA, 0); + + + /* Skip leading whitespace + */ + for (ip=result; isspace(*ip) || *ip == '\n'; ip++) + ; + sres = ip; + + /* Count the number of result records, and skip the header line. + */ + for (nrows=0, ip=sres; *ip; ip++) { + if (*ip == '\n') + nrows++; + } + if (nrows > 0) + nrows--; + + if (nrows <= 0) { + if (debug) + fprintf (stderr, "WARNING: No Data found.\n"); + return (0); + } + + /* Return the row count only if we're not extracting anything. + */ + if (!extract) + return (nrows); + + + /* Get the desired column indices. + */ + ip = &result[1]; + colnum = 0; + bzero ((lp = hline), SZ_RESULT); + while (1) { + bzero (col, SZ_LINE); + for (op=col; *ip && *ip != delim && *ip != '\n';) + *op++ = *lp++ = *ip++; + + if ((*ip == delim && *(ip+1) == delim) || !col[0]) {/* no UCD */ + colnum+=2; + ip += 2; + bzero (col, SZ_LINE); + continue; + } + + + if ((strcasecmp ("ID_MAIN", col) == 0) || + (strcasecmp ("meta.id;meta.main", col) == 0)) + id = colnum; + else if ((strcasecmp ("POS_EQ_RA_MAIN", col) == 0) || + (strcasecmp ("pos.eq.ra;meta.main", col) == 0)) + ra = colnum; + else if ((strcasecmp ("POS_EQ_DEC_MAIN", col) == 0) || + (strcasecmp ("pos.eq.dec;meta.main", col) == 0)) + dec = colnum; + + else if (strcasecmp ("VOX:Image_AccessReference", col) == 0) + acref = colnum; + else if (strcasecmp ("meta.ref.url", col) == 0) + acref = colnum; + else if (strcasecmp ("DATA_LINK", col) == 0) + acref = colnum; + + while (*ip == delim && *ip != '\n') /* Skip the delimiter. */ + *lp++ = *ip++; + + if (*ip == '\n') { /* Only process first line here */ + *lp++ = *ip; + break; + } + colnum++; + } + ncols = colnum + 1; + + if (debug) { + printf ("%s: %c id=%d ra=%d dec=%d acref=%d extract=%d (%d,%d)\n", + pars->name, vot_svcTypeCode(pars->type), id, ra, dec, + acref, extract, ncols, nrows); + } + + /* Begin processing. + */ + for (ip=sres; *ip != '\n'; ip++) ; /* skip header line */ + ip++; + + bzero (s_id, SZ_LINE); + bzero (s_ra, SZ_LINE); + bzero (s_dec, SZ_LINE); + bzero (s_acref, SZ_URL); + bzero (line, SZ_RESULT); + + if (extract & EX_POS && (abs(ra) >= 0 && abs(dec) >= 0)) { + bzero (pfname, SZ_LINE); + strcpy (pfname, vot_openExFile (pars, nrows, "pos", &pfd) ); + } + if (extract & EX_ACREF && acref >= 0) { + bzero (afname, SZ_LINE); + strcpy (afname, vot_openExFile (pars, nrows, "urls", &afd) ); + } + if ((extract & EX_KML) && (abs(ra) >= 0 && abs(dec) >= 0)) { + bzero (kfname, SZ_LINE); + strcpy (kfname, vot_openExFile (pars, nrows, "kml", &kfd) ); + + vot_initKML (kfd, pars); + } + if (extract & EX_HTML) { + if (output && output[0] == '-') { + hfd = stdout; + } else { + bzero (hfname, SZ_LINE); + strcpy (hfname, vot_openExFile (pars, nrows, "html", &hfd) ); + } + + vot_initHTML (hfd, pars); + vot_printHTMLRow (hfd, hline, TRUE, 0); + } + +#ifdef FD_DEBUG + fprintf (stderr, "%s: pfd=%d afd=%d kfd=%d hfd=%d\n", + pars->name, (int)pfd, (int)afd, (int)kfd, (int)hfd); +#endif + + colnum = 0; + rownum = 1; + np = 0; + na = 0; + strcpy (line, hline); + lp = line + strlen (line); + + while (*ip) { + memset (col, 0, SZ_LINE); /* get value */ + for (op=col; *ip && *ip != delim && *ip != '\n';) + *op++ = *lp++ = *ip++; + + *lp++ = *ip; /* save to line buffer */ + if (*ip && *ip != '\n') /* skip the delimiter */ + ip++; + + if (id >= 0 && colnum == id) + strcpy (s_id, vot_normalize(col)); + else if (ra >= 0 && colnum == ra) + strcpy (s_ra, vot_normalizeCoord(col)); + else if (dec >= 0 && colnum == dec) + strcpy (s_dec, vot_normalizeCoord(col)); + else if (acref >= 0 && colnum == acref) + strcpy (s_acref, col); + + if (*ip == '\n') { + if (pfd) { + if (s_id[0]) + fprintf (pfd, "%s\t%s\t%s\n", + vot_normalize(s_id), s_ra, s_dec); + else + fprintf (pfd, "obj%03d\t%s\t%s\n", rownum, s_ra, s_dec); + np++; + } + + if (afd && s_acref[0]) { + fprintf (afd, "%s\n", s_acref); + na++; + } + if (kfd) { + /* See if we're sampling the output. */ + if (row_count < kml_max) { + if (!kml_sample || (row_count % kml_sample) == 0) { + vot_printKMLPlacemark (kfd, s_id, atof(s_ra), + atof(s_dec), line, s_acref, pars); + } + } + } + if (hfd) + vot_printHTMLRow (hfd, line, FALSE, row_count); + + if (kfd || hfd) { + bzero (line, SZ_RESULT); + strcpy (line, hline); + lp = line + strlen (line); + } + + colnum = 0; /* reinitialize */ + rownum++; + bzero (s_id, SZ_LINE); + bzero (s_ra, SZ_LINE); + bzero (s_dec, SZ_LINE); + bzero (s_acref, SZ_URL); + ip++; + + row_count++; + } else + colnum++; + } + if (debug) printf ("%s: np = %d na = %d\n", pars->name, np, na); + + if (pfd) { + fclose (pfd); + if (!np) unlink (pfname); + } + if (afd) { + fclose (afd); + if (!na) unlink (afname); + } + if (hfd) vot_closeHTML (hfd); + if (kfd) vot_closeKML (kfd); + + + return (nrows); +} + + +/************************************************************************ +** Open an extraction file. +*/ +char * +vot_openExFile (svcParams *pars, int nrows, char *extn, FILE **ofd) +{ + static char fname[SZ_LINE]; + FILE *fd = (FILE *) NULL; + + bzero (fname, SZ_LINE); + strcpy (fname, (use_name ? + vot_getOFName (pars, extn, (int)getpid()) : + vot_getOFIndex (pars, extn, (int)getpid())) ); + + if ((fd = fopen (fname, "w+")) == (FILE *) NULL) { + fprintf (stderr, "exiting ERROR opening position file\n"); + vot_dalExit (E_NONE, nrows); + } + + *ofd = fd; + return ( fname ); +} + + +/************************************************************************ +** Construct a standard filename from the service params. +*/ +char * +vot_getOFName (svcParams *pars, char *extn, int pid) +{ + static char fname[SZ_LINE], *root, spid[16]; + + + bzero (fname, SZ_LINE); + bzero (spid, 16); + sprintf (spid, "_%d", pid); + + + /* Create the root part of the name. */ + if (simple_out) { + sprintf (fname, "%s_%s", vot_normalize (pars->name), pars->oname); + + } else if (output) { + root = (output[0] == '-' ? "tmp" : output); + + if (numout) + sprintf (fname, "%s_%03d_%03d", root, + pars->svc_index, pars->obj_index); + else if (nservices == 1 && nobjects > 1) + sprintf (fname, "%s_%03d", root, pars->index); + + else if (nservices > 1 && nobjects == 1) + sprintf (fname, "%s_%s", root, vot_normalize(pars->name)); + + else if (nservices > 1 || nobjects > 1) + sprintf (fname, "%s_%s_%c_%03d_%s", + root, + vot_normalize (pars->name), + vot_svcTypeCode(pars->type), pars->index, spid); + else + strcpy (fname, root); + + } else { + + if (nservices==1 && nobjects > 1) + sprintf (fname, "%s_%s", vot_normalize (pars->name), pars->oname); + else + sprintf (fname, "%s_%c_%s", + vot_normalize (pars->name), + vot_svcTypeCode(pars->type), + (pars->oname[0] ? pars->oname : "pos")); + + if (nservices > 1) + strcat (fname, spid); + } + + if (extn) { + strcat (fname, "."); + strcat (fname, extn); + } + + return (fname); +} + + +char * +vot_getOFIndex (svcParams *pars, char *extn, int pid) +{ + static char fname[SZ_LINE], *root, spid[16]; + + bzero (fname, SZ_LINE); + bzero (spid, 16); + sprintf (spid, "_%d", pid); + + + /* Create the root part of the name. */ + if (output) { + root = (output[0] == '-' ? "tmp" : output); + + if (numout) + sprintf (fname, "%s_%03d_%03d", root, + pars->svc_index, pars->obj_index); + + else if (nservices == 1 && nobjects > 1) + sprintf (fname, "%s_%03d", root, pars->index); + + else if (nservices > 1 && nobjects == 1) + sprintf (fname, "%s_%s", root, vot_normalize(pars->name)); + + else if (nservices > 1 || nobjects > 1) + sprintf (fname, "%s_%s_%c_%03d_%s", + root, + vot_normalize (pars->name), + vot_svcTypeCode(pars->type), pars->index, spid); + else + strcpy (fname, root); + + } else { + + if (nservices==1 && nobjects > 1) + sprintf (fname, "%s_%03d", vot_normalize (pars->name), pars->index); + else + sprintf (fname, "%s_%c_%03d", + vot_normalize (pars->name), + vot_svcTypeCode(pars->type), pars->index); + + if (nservices > 1) + strcat (fname, spid); + } + + if (extn) { + strcat (fname, "."); + strcat (fname, extn); + } + + return (fname); +} + + +/************************************************************************ +** COUNTRESULTS -- Count the number of results in a raw VOTable. +*/ +int +vot_countResults (char *result) +{ + int nrows = 0; + char *tr = (char *) result, + *pos = (char *) result; + + + /* Count the number of <TR> elements in the table. Note we assume + ** there is only a single resource, or that the totatl count is what + ** we desire. Allow for upper or lower-case tag names. + */ + while (tr) { + if ((tr = strstr (pos, "<TR>")) || (tr = strstr (pos, "<tr>"))) + pos = tr + 4, nrows++; + else + break; + } + + return (nrows); +} + + +/************************************************************************ +** Exit the process with the given code. Before leaving, we create a +** semaphore based on the pid and set the value to be the result count. +** This allows us to pass back the information to the parent thread when +** setting the status. +*/ +void +vot_dalExit (int code, int count) +{ + int rc, sem_id, id = getpid(); + int status = code; + + if ((sem_id = semget ((key_t)id, 1, IPC_CREAT | 0777)) >= 0) + rc = semctl (sem_id, 0, SETVAL, count); + +/* + exit (code); +*/ + pthread_exit ((void *) &status); +} + + +/************************************************************************ +** Print the header for the result table. +*/ +void +vot_printHdr (int fd, svcParams *pars) +{ + char buf[SZ_LINE]; + + bzero (buf, SZ_LINE); + sprintf (buf, "# Service: %s\n# Title: %-64.64s\n", + pars->name, pars->title); + write (fd, buf, strlen (buf)); + + bzero (buf, SZ_LINE); + sprintf (buf, + "# ObjName: %s\n# Position: %f %f\n# Size: %f\n", + pars->oname, pars->ra, pars->dec, pars->sr); + write (fd, buf, strlen (buf)); + + bzero (buf, SZ_LINE); + sprintf (buf, "# Query Date: %s\n#\n", vot_procTimestamp()); + write (fd, buf, strlen (buf)); +} + + +/************************************************************************ +** Print the header for the result count table. +*/ +void +vot_printCountHdr () +{ + extern int format, nobjects; + + + if (quiet) + return; + + if (format == F_CSV && count == 0) { + if (use_name || all_named) + fprintf (stderr, "# %sService,%sNRecs\n", + ((nobjects > 1) ? "Rec," : ""), + ((nobjects > 1) ? "ObjName," : "")); + else + fprintf (stderr, "# %sService,%sNRecs\n", + ((nobjects > 1) ? "Rec," : ""), + ((nobjects > 1) ? "RA,Dec," : "")); + } else if (!meta) { + extern int inventory; + + if (nobjects == 1 || inventory) { + fprintf (stderr, "# %-20s %s %s\n# %-20.20s %s %s\n", + "Service", "NRec", "Typ Resource Title", + "-------", "----", + "--- ---------------------------------------------"); + + } else { + if (use_name || all_named) { + fprintf (stderr, "# %3s %-12.12s\t%-15.15s\t%s\n", + "Rec", "Service", "Source Name", "NRecs\n"); + fprintf (stderr, "# %3s %-12.12s\t%-15.15s\t%s\n", + "---", "-------", "-----------", "-----"); + } else { + fprintf (stderr, "# %3s %-12.12s\t %-24.24s\t%s\n", + "Rec", "Service", " RA Dec", "NRecs"); + fprintf (stderr, "# %3s %-12.12s\t %-24.24s\t%s\n", + "---", "-------", "-----------------------", "-----"); + } + } + } +} + + +/************************************************************************ +** Print an individual line of the result count table. +*/ +int +vot_printCount (Query query, svcParams *pars, int *res_count) +{ + QResponse qr = (QResponse) 0; /* Query response */ + int nrec; + + + if ((qr = voc_executeQuery (query)) <= 0) { + return (E_REQFAIL); + + } else { + nrec = voc_getRecordCount(qr); + *res_count = nrec; + + if (count_only && nrec <= 0) + return (E_NODATA); + if (count < 0 && nrec > 0) + return (E_NODATA); + if (nrec <= 0) + return (E_NODATA); + + vot_printCountLine (nrec, pars); + return (E_NONE); + } + + return (E_NONE); +} + + +/************************************************************************ +** Print an individual line of the result count table. +*/ +void +vot_printCountLine (int nrec, svcParams *pars) +{ + int fmt; + extern int nobjects; + extern void ppMultiLine(); + extern char *toSexa(); + + + if (nrec == 0 || quiet) + return; + + fmt = (count == 1) ? F_ASCII : pars->fmt; +fmt = F_ASCII; + + switch (fmt) { + case F_CSV|F_HTML: + case F_CSV|F_KML: + case F_TSV: + case F_ASCII: + if (nobjects == 1) { + printf (" %-20.20s %4d %c ", + pars->name, nrec, + vot_svcTypeCode (pars->type)); + ppMultiLine (pars->title, 35, 45, 1024); + printf ("\n"); + } else if (use_name || all_named) { + printf (" %3d %-12.12s\t%-15.15s\t%6d\n", + pars->index, pars->name, pars->oname, nrec); + } else { + /* + printf (" %3d %-12.12s\t%10.6f %10.6f\t%6d", + pars->index, pars->name, pars->ra, pars->dec, nrec); + */ + printf (" %3d %-12.12s\t", pars->index, pars->name); + printf ("%12.12s ", toSexa (pars->ra/15.0)); + printf ("%12.12s\t%5d", toSexa(pars->dec), nrec); + if (pars->oname[0] && pars->oname && strcmp ("none", pars->oname)) + printf (" (%s)", pars->oname); + printf ("\n"); + } + break; + case F_CSV: + if (nobjects == 1) { + printf ("%s,%d,%s\n", pars->name, nrec, pars->title); + } else if (use_name || all_named) { + printf ("%d,%s,%s,%d\n", + pars->index, pars->name, pars->oname, nrec); + } else { + /* + printf ("%d,%s,%.6f,%.6f,%d\n", + pars->index, pars->name, pars->ra, pars->dec, nrec); + */ + printf ("%d,%s,", pars->index, pars->name); + printf ("%s,", toSexa (pars->ra/15.0)); + printf ("%s,%d\n", toSexa (pars->dec), nrec); + } + break; + case F_FITS: + fprintf (stderr, "FITS binary table not yet supported\n"); + break; + default: + break; + } +} + + +/************************************************************************ +** Return a simple character type code for the specified service type. +*/ +char +vot_svcTypeCode (int type) +{ + switch (type) { + case SVC_CONE: return ('C'); break; + case SVC_SIAP: return ('I'); break; + case SVC_SSAP: return ('S'); break; + case SVC_VIZIER: return ('T'); break; + case SVC_OTHER: return ('?'); break; + } + + return ('?'); +} + + +/************************************************************************ +** GETEXTN -- Get the filename extension given the current format. +*/ +char * +vot_getExtn () +{ + if (format & F_CSV) /* figure out the extension */ + return ("csv"); + else if (format & F_ASCII) + return ("asv"); + else if (format & F_TSV) + return ("tsv"); + else if (format & F_RAW) + return ("xml"); + else if (format & F_KML) + return ("kml"); + else if (format & F_XML) + return ("xml"); + + return ((char *) NULL); +} + + +/************************************************************************ +** PROCTIMESTAMP -- Return the timestamp with the system newline removed. +*/ +char * +vot_procTimestamp () +{ + time_t clock = time (0); + char *tstr = ctime (&clock); + + tstr[24] = '\0'; /* kill the newline */ + + return (tstr); +} + + + +/************************************************************************ +** CONCAT -- Concatenate the files generated by the query into a +** single document ordered by the service. +*/ +void +vot_concat () +{ + FILE *fd = (FILE *) NULL; + Service *svc = svcList; /* the service list */ + Proc *proc; /* process list in each service */ + char *extn, fname[SZ_FNAME]; + int nrows = 0; + + + extn = vot_getExtn (); /* figure out the extension */ + + for (svc=svcList; svc; svc=svc->next) { + + if (output && output[0] == '-') { + fd = stdout; + } else { + /* Open a separate file for each service. Since we can't rely + ** one services returning the same columns it only makes sense + ** to concatenate similar files. + */ + bzero (fname, SZ_FNAME); + sprintf (fname, "%s_%d.%s", + vot_getSName(svc->proc->root), getpid(), extn); + + if ((fd = fopen (fname, "w+")) == (FILE *) NULL) { + fprintf (stderr, "ERROR: Cannot open output file: '%s'\n", + fname); + continue; + } + } + + /* Concatenate results for each object. + */ + nrows = 0; + for (proc=svc->proc; proc; proc=proc->next) + nrows += vot_copyFile (proc->root, extn, vot_getOName(proc->root), + fd, (proc == svc->proc), nrows); + + if (fd != stdout) /* close the file descriptor */ + fclose (fd); + } + + /* Clean up the intermediate files if needed. + */ + if (fd == stdout || (extract & EX_COLLECT)) + vot_clean (extn); +} + + +/************************************************************************ +** COPYFILE -- Copy a result file to the output XML file. +*/ +static int +vot_copyFile (char *root, char *extn, char *name, FILE *fd, int hdr, int nrows) +{ + char line[4096], fname[SZ_FNAME]; + FILE *ifd; + int nr = 0; + + + bzero (fname, SZ_FNAME); + sprintf (fname, "%s.%s", root, extn); + + if (access (fname, R_OK) == 0) { + if ((ifd = fopen (fname, "r")) == (FILE *) NULL) { + fprintf (stderr, "Warning: Cannot open file '%s'\n", fname); + return (0); + } + } else + return (0); + + /* (Slow) Copy the file until the end of the Document. + */ + bzero (line, 4096); + while (fgets (line, 4096, ifd)) { + if (!nrows && hdr && line[0] == '#') + /*fprintf (fd, "# %s", &line[1]); */ + fprintf (fd, "%s", &line[1]); + else if (nrows && !hdr && line[0] == '#') + ; + else { + fprintf (fd, "%s", line); + nr++; + } + bzero (line, 4096); + } + fflush (fd); + + fclose (ifd); + + return (nr); +} + + +/************************************************************************ +** CLEANXML -- Clean up the intermediate VOTable files when producing +** the compiled XML doc.. +*/ +static void +vot_clean (char *extn) +{ + Service *svc = svcList; /* the service list */ + Proc *proc; /* process list in each service */ + char fname[SZ_FNAME]; + + for (svc=svcList; svc; svc=svc->next) { + for (proc=svc->proc; proc; proc=proc->next) { + bzero (fname, SZ_FNAME); + sprintf (fname, "%s.%s", proc->root, extn); + unlink (fname); + } + } +} diff --git a/vendor/voclient/voapps/lib/voFITS.c b/vendor/voclient/voapps/lib/voFITS.c new file mode 100644 index 00000000..b6d9c48e --- /dev/null +++ b/vendor/voclient/voapps/lib/voFITS.c @@ -0,0 +1,467 @@ +#include <string.h> +#include <stdio.h> +#include <math.h> +#include <unistd.h> +#include "voApps.h" +#include "fitsio.h" + + +#define MAX_IMAGES 20480 /* max images to process */ + +#define dabs(x) ((x<0.0?-x:x)) + + +/** + * Private methods. + */ +static void vot_printFrameInfo (FILE *fd, frameInfo *im); +static int vot_getFrameWcs (fitsfile *fptr, frameInfo *info); + +extern int vot_fileType (char *name); + + + + +/** + * VOT_IMAGEINFO -- Get information about a FITS file structure and WCS. + * + * @fn info = vot_imageInfo (char *name, int do_all) + * + * @brief Get information about a FITS file structure and WCS. + * @param name name of FITS file to open + * @param do_all do all extensions in an MEF file? + * @return pointer to ImInfo structure + */ +ImInfo * +vot_imageInfo (char *name, int do_all) +{ + fitsfile *fptr; + ImInfo *info = (ImInfo *) NULL; + long naxes[3] = {0, 0, 0}, nrows=0; + int nextns=0, naxis=0, bitpix=0, extnum=0; + int hdupos=0, hdutype=0, ncols=0, i=0, status=0; + double cxsum=0.0, cysum=0.0, rxsum=0.0, rysum=0.0; + + + /* Check for file existence. + */ + if (access (name, F_OK) != 0) { + fprintf (stderr, "Error: cannot open image '%s'\n", name); + return ((ImInfo *) NULL); + } + if (vot_fileType (name) != VOT_FITS) { + fprintf (stderr, "Error: file '%s' is not a FITS image\n", name); + return ((ImInfo *) NULL); + } + + info = (ImInfo *) calloc (1, sizeof (ImInfo)); + if (fits_open_file (&fptr, name, READONLY, &status) == 0) { + fits_get_num_hdus (fptr, &nextns, &status); + fits_get_hdu_num (fptr, &hdupos); /* get the current HDU position */ + + strncpy (info->imname, name, strlen(name)); + info->nextend = (nextns - 1); + info->extns = (frameInfo *) calloc (nextns, sizeof (frameInfo)); + + for (; !status; hdupos++) { /* Main loop for each HDU */ + fits_get_hdu_type (fptr, &hdutype, &status); /* Get the HDU type */ + + if (hdutype == IMAGE_HDU) { /* primary array or image HDU */ + fits_get_img_param (fptr, 10, &bitpix, &naxis, naxes, &status); + + if (hdupos == 0) { /* PHU */ + info->frame.is_image = 1; + info->frame.is_table = 0; + info->frame.naxis = naxis; + info->frame.bitpix = bitpix; + for (i=0; i < naxis; i++) + info->frame.naxes[i] = naxes[i]; + + } else { /* EHU */ + extnum = hdupos - 1; + info->extns[extnum].is_image = 1; + info->extns[extnum].is_table = 0; + info->extns[extnum].extnum = extnum; + info->extns[extnum].naxis = naxis; + info->extns[extnum].bitpix = bitpix; + for (i=0; i < naxis; i++) + info->extns[extnum].naxes[i] = naxes[i]; + + if (vot_getFrameWcs (fptr, &info->extns[extnum]) == 0) + info->extns[extnum].has_wcs = 1; + } + + } else { /* a table HDU */ + if (hdupos > 0) { /* EHU */ + fits_get_num_rows (fptr, &nrows, &status); + fits_get_num_cols (fptr, &ncols, &status); + + extnum = hdupos - 1; + info->extns[extnum].is_image = 0; + info->extns[extnum].is_table = 1; + info->extns[extnum].naxis = 2; + info->extns[extnum].bitpix = 0; + info->extns[extnum].naxes[0] = ncols; + info->extns[extnum].naxes[1] = nrows; + } + +#ifdef GET_TBLINFO + printf ("%s Table: %d columns x %ld rows\n", + ((hdutype==ASCII_TBL) ? "ASCII" : "Binary"); ncols, nrows); + printf(" COL NAME FORMAT\n"); + for (i = 1; i <= ncols; i++) { + fits_make_keyn ("TTYPE", i, keyname,&status); + fits_read_key (fptr, TSTRING, keyname,colname,NULL,&status); + fits_make_keyn ("TFORM", i, keyname,&status); + fits_read_key (fptr, TSTRING, keyname,coltype,NULL,&status); + printf(" %3d %-16s %-16s\n", i, colname, coltype); + } +#endif + } + + /* Move to next extension. + */ + fits_movrel_hdu (fptr, 1, NULL, &status); + } + + if (status == END_OF_FILE) + status = 0; /* reset normal error */ + + } else if (status) /* print any error message */ + fits_report_error (stderr, status); + + + /* Compute the values for the entire frame. + */ + info->frame.lx = info->frame.ly = 360.0; + info->frame.ux = info->frame.uy = -360.0; + + info->frame.cx = info->extns[0].cx; + info->frame.cy = info->extns[0].cy; + info->frame.lx = info->extns[0].lx; + info->frame.ly = info->extns[0].ly; + info->frame.ux = info->extns[0].ux; + info->frame.uy = info->extns[0].uy; + info->frame.rotang = info->extns[0].rotang; + info->frame.xrval = info->extns[0].xrval; + info->frame.yrval = info->extns[0].yrval; + info->frame.xrpix = info->extns[0].xrpix; + info->frame.yrpix = info->extns[0].yrpix; + info->frame.radius = info->extns[0].radius; + + if (nextns == 1) { + for (i=0; i < naxis; i++) + info->frame.naxes[i] = info->extns[0].naxes[i]; + } + memcpy (&info->frame.xc[0], &info->extns[0].xc[0], (sizeof(double)*4)); + memcpy (&info->frame.yc[0], &info->extns[0].yc[0], (sizeof(double)*4)); + + for (i=1; i < nextns; i++) { + if (info->extns[i].lx < info->frame.lx) + info->frame.lx = info->extns[i].lx; + if (info->extns[i].ly < info->frame.ly) + info->frame.ly = info->extns[i].ly; + + if (info->extns[i].ux > info->frame.ux) + info->frame.ux = info->extns[i].ux; + if (info->extns[i].uy > info->frame.uy) + info->frame.uy = info->extns[i].uy; + cxsum += info->extns[i].cx; + cysum += info->extns[i].cy; + + rxsum += info->extns[i].naxes[0]; + rysum += info->extns[i].naxes[1]; + + info->frame.scale = info->extns[i].scale; + info->frame.rotang = info->extns[i].rotang; + strcpy (info->frame.ctype, info->extns[i].ctype); + } + + if (nextns > 1) { + info->frame.xrval = info->frame.cx = (cxsum / (double) nextns); + info->frame.yrval = info->frame.cy = (cysum / (double) nextns); + info->frame.xrpix = info->frame.radius / + (info->frame.scale / 3600.) / 2.0; + info->frame.yrpix = info->frame.radius / + (info->frame.scale / 3600.) / 2.0; + } else { + info->frame.xrval = info->frame.cx = info->extns[0].cx; + info->frame.yrval = info->frame.cy = info->extns[0].cy; + info->frame.xrpix = info->extns[0].xrpix; + info->frame.yrpix = info->extns[0].yrpix; + strcpy (info->frame.ctype, info->extns[0].ctype); + } + + info->frame.width = ((info->frame.ux+360.) - (info->frame.lx+360.)); + info->frame.height = ((info->frame.uy+ 90.) - (info->frame.ly+ 90.)); + info->frame.radius = sqrt ( + (info->frame.cx - info->frame.lx) * + (info->frame.cx - info->frame.lx) + + (info->frame.cy - info->frame.ly) * + (info->frame.cy - info->frame.ly) ); + info->frame.xc[0] = info->frame.lx; info->frame.yc[0] = info->frame.ly; + info->frame.xc[1] = info->frame.lx; info->frame.yc[1] = info->frame.uy; + info->frame.xc[2] = info->frame.ux; info->frame.yc[2] = info->frame.uy; + info->frame.xc[3] = info->frame.ux; info->frame.yc[3] = info->frame.ly; + + + fits_close_file (fptr, &status); + return ( (ImInfo *) info); +} + + +/** + * VOT_IMAGENEXTNS -- Get the number of extensions in an MEF file. + * + * @fn nextn = vot_imageNExtns (char *name) + * + * @brief Get the number of extensions in an MEF file. + * @param name name of FITS file to open + * @return number of extensions in an MEF file + */ +int +vot_imageNExtns (char *image) +{ + fitsfile *fptr; + int nextns = -1, status = 0; + + + if (fits_open_file (&fptr, image, READONLY, &status) == 0) { + fits_get_num_hdus (fptr, &nextns, &status); + fits_close_file (fptr, &status); + } + + return (nextns); +} + + +/** + * VOT_PRINTIMAGEINFO -- Print the image information. + * + * @fn vot_printImageInfo (FILE *fd, ImInfo *im) + * + * @brief Print the image information. + * @param fd output file descriptor (or stdout/stderr) + * @param im image information structure + * @return nothing + */ +void +vot_printImageInfo (FILE *fd, ImInfo *im) +{ + register int i; + + fprintf (fd, "Name: %s nextns = %d\n", im->imname, im->nextend); + + fprintf (fd, "Frame:\n"); im->frame.extnum = -1; + vot_printFrameInfo (fd, &im->frame); + + for (i=1; i < im->nextend; i++) + vot_printFrameInfo (fd, &im->extns[i]); +} + + +/** + * VOC_FREEIMAGEINFO -- Free the image information structure. + * + * @fn vot_freeImageInfo (ImInfo *im) + * + * @brief Free the image information structure. + * @param im image information structure + * @return nothing + */ +void +vot_freeImageInfo (ImInfo *im) +{ + free ((void *) im->extns); /* extension structs */ + free ((void *) im); /* main image structs */ +} + + + +/**************************************************************************** + *** Private procedures + ****************************************************************************/ + +/** + * VOT_PRINTFRAMEINFO -- Print information about a specific frame. + */ +static void +vot_printFrameInfo (FILE *fd, frameInfo *im) +{ + if (im->extnum >= 0) { + fprintf (fd, "\nExt: %d dims[%d] = %d %d %d\t", + im->extnum, im->naxis, im->naxes[0], im->naxes[1], im->naxes[2]); + fprintf (fd, " image: %d table: %d has_wcs: %d flip: %d\n", + im->is_image, im->is_table, im->has_wcs, im->axflip); + } + + fprintf (fd, + " center: %8.4f %8.4f ll: %8.4f %8.4f ur: %8.4f %8.4f\n", + im->cx, im->cy, im->lx, im->ly, im->ux, im->uy); + fprintf (fd, " corners: %8.4f %8.4f %8.4f %8.4f\n", + im->xc[1], im->yc[1], im->xc[2], im->yc[2]); + fprintf (fd, "\t %8.4f %8.4f %8.4f %8.4f\n", + im->xc[0], im->yc[0], im->xc[3], im->yc[3]); + fprintf (fd, + " crval: %8.4f %8.4f crpix: %8.4f %8.4f ctype: '%s'\n", + im->xrval, im->yrval, im->xrpix, im->yrpix, im->ctype); + fprintf (fd, + " w/h: %8.4f %8.4f radius: %8.4f rot: %8.4f scale: %8.4f\n", + dabs(im->width), dabs(im->height), im->radius, im->rotang, im->scale); +} + + +/** + * VOT_GETFRAMEWCS -- Get the WCS information for a given frame. + */ +static int +vot_getFrameWcs (fitsfile *fptr, frameInfo *info) +{ + double xrval=0.0, yrval=0.0, xrpix=0.0, yrpix=0.0, xpix=0.0, ypix=0.0; + double xinc=0.0, yinc=0.0, rot=0.0, scale=0.0, xrot=0.0, yrot=0.0; + double cx=0.0, cy=0.0, lx=0.0, ly=0.0, ux=0.0, uy=0.0; + double cd11=0.0, cd12=0.0, cd21=0.0, cd22=0.0, cdelt1=0.0, cdelt2=0.0; + int i, axflip=0, status = 0; + char str[32], ctype[5], comment[80]; + + + /* Get the header WCS keywords. + */ + fits_read_img_coord (fptr, &xrval, &yrval, &xrpix, + &yrpix, &xinc, &yinc, &rot, ctype, &status); + + info->xrval = xrval; + info->yrval = yrval; + info->xrpix = xrpix; + info->yrpix = yrpix; + info->has_wcs = 1; + info->is_image = 1; + strcpy (info->ctype, ctype); + + xpix = (double) 0.5; /* Lower-left */ + ypix = (double) 0.5; + status = 0; + fits_pix_to_world (xpix, ypix, xrval, yrval, xrpix, yrpix, xinc, yinc, + rot, ctype, &info->xc[0], &info->yc[0], &status); + + xpix = (double) 0.5; /* Upper-left */ + ypix = (double) info->naxes[1] - 0.5; + status = 0; + fits_pix_to_world (xpix, ypix, xrval, yrval, xrpix, yrpix, xinc, yinc, + rot, ctype, &info->xc[1], &info->yc[1], &status); + + xpix = (double) info->naxes[0] - 0.5; /* Upper-right */ + ypix = (double) info->naxes[1] - 0.5; + status = 0; + fits_pix_to_world (xpix, ypix, xrval, yrval, xrpix, yrpix, xinc, yinc, + rot, ctype, &info->xc[2], &info->yc[2], &status); + + xpix = (double) info->naxes[0] - 0.5; /* Lower-right */ + ypix = (double) 0.5; + status = 0; + fits_pix_to_world (xpix, ypix, xrval, yrval, xrpix, yrpix, xinc, yinc, + rot, ctype, &info->xc[3], &info->yc[3], &status); + + xpix = (double) info->naxes[0] / 2. - 0.5; /* Center */ + ypix = (double) info->naxes[1] / 2. - 0.5; + status = 0; + fits_pix_to_world (xpix, ypix, xrval, yrval, xrpix, yrpix, xinc, yinc, + rot, ctype, &info->cx, &info->cy, &status); + info->cx = xrval; + info->cy = yrval; + + /* Get center and cone radius. + */ + lx = info->lx = info->xc[0]; /* Lower-left */ + ly = info->ly = info->yc[0]; + ux = info->ux = info->xc[2]; /* Upper-right */ + uy = info->uy = info->yc[2]; + cx = info->cx; + cy = info->cy; + status = 0; + if ((i = fits_read_key_dbl(fptr, "CD1_1", &cd11, comment, &status))==0) { + fits_read_key_dbl (fptr, "CD1_2", &cd12, comment, &status); + fits_read_key_dbl (fptr, "CD2_1", &cd21, comment, &status); + fits_read_key_dbl (fptr, "CD2_2", &cd22, comment, &status); + + scale = 3600.0 * sqrt ((cd11*cd11+cd21*cd21+cd12*cd12+cd22*cd22) / 2.); + xrot = dabs (atan2 ( cd21, cd11)); + yrot = dabs (atan2 (-cd12, cd22)); + rot = (xrot + yrot) / 2.0; + } else { + /* Old-style keywords. + */ + status = 0; + if (!fits_read_key_dbl (fptr, "CDELT1", &cdelt1, comment, &status)) { + fits_read_key_dbl (fptr, "CDELT2", &cdelt2, comment, &status); + + scale = 3600.0 * sqrt ((cdelt1*cdelt1 + cdelt2*cdelt2) / 2.); + + if (!fits_read_key_dbl (fptr, "CROTA1", &xrot, comment, &status)) { + fits_read_key_dbl (fptr, "CROTA2", &yrot, comment, &status); + rot = (xrot + yrot) / 2.0; + } + } else + info->has_wcs = 0; + } + + status = 0; + memset (str, 0, 32); + if ((i = fits_read_key_str(fptr, "CTYPE1", str, comment, &status))==0) { + if (strncasecmp (str,"DEC",3) == 0 || strncasecmp (str,"LAT",3) == 0) + axflip = 1; + } + + /* For a bad/approximate WCS, compute in rough coords. + */ + if ( (lx == cx) && (ly == cy) ) { + double s = (scale / 3600.0); + + lx = info->lx = cx - (info->naxes[0]/2 * s); /* Lower-left */ + ly = info->ly = cy - (info->naxes[1]/2 * s); + ux = info->ux = cx + (info->naxes[0]/2 * s); /* Upper-right */ + uy = info->uy = cy + (info->naxes[1]/2 * s); + + info->xc[0] = cx - (info->naxes[0]/2 * s); /* Lower-left */ + info->yc[0] = cy - (info->naxes[1]/2 * s); + + info->xc[1] = cx - (info->naxes[0]/2 * s); /* Upper-left */ + info->yc[1] = cy + (info->naxes[1]/2 * s); + + info->xc[2] = cx + (info->naxes[0]/2 * s); /* Upper-right */ + info->yc[2] = cy + (info->naxes[1]/2 * s); + + info->xc[3] = cx + (info->naxes[0]/2 * s); /* Lower-right */ + info->yc[3] = cy - (info->naxes[1]/2 * s); + } + + /* FIXME -- Doens't handle rotation properly. */ + info->width = dabs((ux - lx)); /* in degrees */ + info->height = dabs((uy - ly)); + info->radius = sqrt ((cx - lx) * (cx - lx) + (cy - ly) * (cy - ly)); + info->rotang = rot; + info->scale = scale; + info->axflip = axflip; + + return (info->has_wcs); +} + + +/***************************************************************************** + * Program main. + ****************************************************************************/ +#ifdef UNIT_TEST +int +main (int argc, char *argv[]) +{ + ImInfo *img = (ImInfo *) NULL; + + + if ( (img = vot_imageInfo (argv[1], 1)) ) { + vot_printImageInfo (stdout, img); + vot_freeImageInfo (img); + } + + return (0); +} +#endif diff --git a/vendor/voclient/voapps/lib/voHTML.c b/vendor/voclient/voapps/lib/voHTML.c new file mode 100644 index 00000000..c50bdb54 --- /dev/null +++ b/vendor/voclient/voapps/lib/voHTML.c @@ -0,0 +1,131 @@ +/************************************************************************ +** VODALUTIL.C -- Utility procedures for the DAL interface worker +** procedures. +** +** M. Fitzpatrick, NOAO, July 2007 +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include "VOClient.h" +#include "voAppsP.h" + + +extern int format, iportal; +extern int html_border, html_color, html_header; + +void vot_initKML (FILE *fd, svcParams *pars); +void vot_printHTMLRow (FILE *fd, char *line, int isHdr, int rownum); +void vot_closeKML (FILE *fd); + + + +/************************************************************************ +** INITHTML -- Initialize the KML output file header. +*/ +void +vot_initHTML (FILE *fd, svcParams *pars) +{ + if (!fd) + return; + + if (html_header) + fprintf (fd, "<html>\n<body>\n"); + + fprintf (fd, "<table border=\"%d\">\n", + (html_border ? 5 : 0)); +} + + +/************************************************************************ +** PRINTHTMLROW -- Write a row in an HTML table. +** file. +*/ +void +vot_printHTMLRow (FILE *fd, char *line, int isHdr, int rownum) +{ + char *ip, *hp, *sp, *dp, *vp, *tab, *col, delim, val[SZ_LINE]; + + + if (!fd || !line) + return; + + for (dp=line; *dp && *dp != '\n'; dp++) /* get the data line */ + ; + dp++; + hp = line; /* get the header line */ + + sp = (isHdr ? hp : dp); + tab = (isHdr ? "th" : "td"); + if (isHdr) + col = "eec"; + else if (html_color) + col = ((rownum % 2) == 0) ? "ccc" : "eee"; + else + col = "fff"; + + delim = ((format == F_CSV) ? ',' : + ((format == F_TSV) ? '\t' : + ((format == F_ASCII) ? ' ' : ','))); + + fprintf (fd, "<tr>"); + + for (ip=sp; *ip; ) { + bzero (val, SZ_LINE); + for (vp=val; *ip && *ip != '\n' && *ip != delim; ) { + if (*ip == '>') { + strcpy (vp, ">"); + vp += 4, ip++; + } else if (*ip == '<') { + strcpy (vp, "<"); + vp += 4, ip++; + } else { + *vp++ = *ip++; + } + } + + if (strncmp (val, "http://", 7) == 0) { + if (iportal && strstr (val, ".fits") == (char *) NULL) { + fprintf (fd, "<%s style=\"background:#%s\">", tab, col); + fprintf (fd, "<a href=\"javascript:render('%s');\">%s</a></%s>", + val, val, tab); + } else if (!iportal) { + fprintf (fd, + "<%s style=\"background:#%s\"><a href='%s'>%s</a></%s>", + tab, col, val, val, tab); + } else { + fprintf (fd, "<%s style=\"background:#%s\">%s</%s>", + tab, col, val, tab); + } + } else + fprintf (fd, "<%s style=\"background:#%s\">%s</%s>", + tab, col, val, tab); + if (*ip) + ip++; + else + break; + } + + fprintf (fd, "</tr>\n"); +} + + +/************************************************************************ +** CLOSEHTML -- Close the HTML output file. +*/ +void +vot_closeHTML (FILE *fd) +{ + if (!fd) + return; + + fprintf (fd, "</table>\n"); + if (html_header) + fprintf (fd, "</body>\n</html>\n"); + + fclose (fd); +} + + diff --git a/vendor/voclient/voapps/lib/voInv.c b/vendor/voclient/voapps/lib/voInv.c new file mode 100644 index 00000000..e6d7cb98 --- /dev/null +++ b/vendor/voclient/voapps/lib/voInv.c @@ -0,0 +1,501 @@ +/************************************************************************** +** +*/ + +/* +** ra, dec, radius // double +** sources, resources, id, return // string +** sourceURL, resourceURL // file +*/ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#ifdef VO_INVENTORY +#include <curl/curl.h> +#include <curl/types.h> +#include <curl/easy.h> +#include "VOClient.h" +#include "voAppsP.h" + + + +char *base_url = + "http://irsa.ipac.caltech.edu/cgi-bin/VOInventory/nph-voInventory"; + +#define SUBSET "subset" /* 1 pos, 1 resource */ +#define MATCHES "matches" /* N pos, 1 resource */ +#define REGION "region" /* 1 pos, [N resources] */ +#define TABLE "table" /* N pos, [N resources] */ + + +#ifdef UNIT_TEST +int verbose = 0; +int debug = 0; +#endif +char *id = NULL; +char *action = NULL; +char *rettype = "votable"; +double ra = 0.0; +double dec = 0.0; +double radius = 0.1; + +char *ofname = NULL; +FILE *outfile = (FILE *) NULL; + +int nsources = 1; +int nresources = 0; + +extern Object *objList; +extern Service *svcList; +extern char *sources; +extern char *resources; +extern double sr; +extern int format, count, verbose, debug, ecols, nservices, nobjects; +extern char *output, *tmpdir; + + +char *vot_doInventory (); +char *vot_execInv (double ra, double dec, double radius, char *sources, + char *resources, char *id, char *rettype, FILE *outfile); + +static size_t vot_invWrite (void *ptr, size_t size, size_t nmemb, FILE *stream); +static size_t vot_invRead (void *ptr, size_t size, size_t nmemb, FILE *stream); +static char *vot_dbl2str (double dval); +static void vot_printRegionCount (char *file, int extra); +static void vot_printMatchCount (char *file); + +extern char *vot_getTableCol (char *line, int col, int span); +extern void ppMultiLine (char *result, int poffset, int pwidth, int maxch); + + + +#ifdef UNIT_TEST +int +main (int argc, char *argv[]) +{ + register int i, j, len; + + CURL *curl; + CURLcode res; + struct curl_httppost *form = NULL; + struct curl_httppost *last = NULL; + + + for (i=1; i < argc; i++) { + if (argv[i][0] == '-') { + len = strlen (argv[i]); + for (j=1; j < len; j++) { + switch (argv[i][j]) { + case 'h': /* help */ + return (0); + case 'd': /* debug */ + debug++; + break; + case 'v': /* verbose */ + verbose++; + break; + case 't': /* test */ + base_url = "http://iraf.noao.edu/scripts/tpost"; + break; + case 'p': /* pos (ra dec) */ + ra = atof (argv[i+1]); + dec = atof (argv[i+2]); + i += 2; + nsources = 1; + break; + case 'r': /* radius */ + radius = atof (argv[++i]); + break; + case 'i': /* id */ + id = argv[++i]; + break; + case 'o': /* output file */ + ofname = argv[++i]; + outfile = fopen (ofname, "w+"); + break; + case 'R': /* resource file */ + resources = argv[++i]; + nresources = 2; + break; + case 'S': /* source file */ + sources = argv[++i]; + nsources = 2; + break; + + case 'A': rettype = "ascii"; break; + case 'C': rettype = "csv"; break; + case 'H': rettype = "HTML"; break; /* BROKE */ + case 'T': rettype = "tsv"; break; + case 'V': rettype = "votable"; break; + default: + break; + } + } + } + } + + + if (debug) { + fprintf (stderr, "pos = (%f,%f) radius = %f\n", ra, dec, radius); + fprintf (stderr, "id = '%s'\n", id); + fprintf (stderr, "sources = '%s' N = %d\n", sources, nsources); + fprintf (stderr, "resources = '%s' N = %d\n", resources, nresources); + } + + (void) vot_execInv (ra, dec, radius, sources, resources, id, rettype, + NULL); + + return 0; +} +#endif + + +/* VOT_EXECINV -- Execute the inventory service call. +*/ +char * +vot_doInventory () +{ + double ra = objList->ra, dec = objList->dec, radius = sr; + char *id = (svcList ? svcList->identifier : NULL), + *rettype = "tsv", *action; + char tmpfile[SZ_LINE]; + FILE *fd = (FILE *) NULL; + + extern char *vot_mktemp(); + + + /* Get a temporary file to be used for the votable output. + */ + strcpy (tmpfile, (debug ? "/tmp/vod.tmp" : vot_mktemp ("vodi"))); + + if (! (fd = fopen (tmpfile, "w+")) ) { + fprintf (stderr, "Cannot open output file '%s'\n", tmpfile); + exit (1); + } + + if (debug) { + fprintf (stderr, "ra '%f' '%f' radius '%f'....\n", ra, dec, radius); + fprintf (stderr, "id '%s' rettype '%s'....\n", id, rettype); + fprintf (stderr, "sources '%s' resources '%s'....\n", + sources, resources); + fprintf (stderr, "using file '%s'....\n", output); + } + + /* Execute the query. + vot_execInv (ra, dec, radius, sources, resources, id, "tsv", fd); + */ + action = vot_execInv (ra, dec, radius, sources, resources, id, "tsv", fd); + + if (fd != stdout) { + fclose (fd); + + if (debug) { + system("cat /tmp/vod.tmp"); + printf ("\n\n"); + } + + if (count) { + if (strcmp (action, "region") == 0) + vot_printRegionCount (tmpfile, 0); + else if (strcmp (action, "table") == 0) + vot_printRegionCount (tmpfile, 1); + else if ((strcmp (action, "matches")) || + (strcmp (action, "subset") == 0)) { + vot_printMatchCount (tmpfile); + } + } + } + + if (!debug) + unlink (tmpfile); + + return (action); +} + + +/* VOT_EXECINV -- Execute the inventory service call. +*/ +char * +vot_execInv (double ra, double dec, double radius, char *sources, + char *resources, char *id, char *rettype, FILE *outfile) +{ + CURL *curl; + CURLcode res; + struct curl_httppost *form = NULL; + struct curl_httppost *last = NULL; + + + + nresources = nservices; + nsources = nobjects; + + /* Initialize the CURL call. + */ + curl_global_init (CURL_GLOBAL_ALL); + + if ( (curl = curl_easy_init()) ) { + + struct curl_slist *headerlist = NULL; + + + /* Fill in the fields. + */ + if (radius > 0.0) { + curl_formadd (&form, &last, CURLFORM_COPYNAME, "radius", + CURLFORM_COPYCONTENTS, vot_dbl2str(radius), CURLFORM_END); + curl_formadd (&form, &last, CURLFORM_COPYNAME, "units", + CURLFORM_COPYCONTENTS, "degree", CURLFORM_END); + } + + if (debug) + fprintf (stderr, "\n\nnsources=%d nresources=%d\n\n", + nsources, nresources); + + switch ( nsources ) { + case 0: + perror ("Invalid NSources=0, no src file or posn specified\n"); + exit(1); + case 1: + curl_formadd (&form, &last, CURLFORM_COPYNAME, "ra", + CURLFORM_COPYCONTENTS, vot_dbl2str(ra), CURLFORM_END); + curl_formadd (&form, &last, CURLFORM_COPYNAME, "dec", + CURLFORM_COPYCONTENTS, vot_dbl2str(dec), CURLFORM_END); + if (id) { + action = "subset"; + curl_formadd (&form, &last, CURLFORM_COPYNAME, "id", + CURLFORM_COPYCONTENTS, id, CURLFORM_END); + } else if (resources) + action = "table"; + else + action = "region"; + break; + default: + if (sources) { + curl_formadd (&form, &last, CURLFORM_COPYNAME, "sources", + CURLFORM_FILE, sources, CURLFORM_END); + if (nresources < 0) + action = "table"; + else if (nresources == 1 && id) + action = "matches"; + else if (resources) + action = "table"; + } else { + perror ("Invalid nsources=N, no source file specified\n"); + exit (1); + } + break; + } + + + /* Set the matching resources. + */ + if (nresources == 1 && id) { + curl_formadd (&form, &last, CURLFORM_COPYNAME, "id", + CURLFORM_COPYCONTENTS, id, CURLFORM_END); + + } else if (nresources >= 1 && resources) { + curl_formadd (&form, &last, CURLFORM_COPYNAME, "resources", + CURLFORM_FILE, resources, + CURLFORM_CONTENTTYPE, "text/xml", + CURLFORM_END); + + } else if (nresources > 0) { + perror ("Invalid NResources=2, no resource file specified\n"); + exit (1); + } + + + /* Make sure we have a valid action to execute. + */ + if (action) { + curl_formadd (&form, &last, CURLFORM_COPYNAME, "action", + CURLFORM_COPYCONTENTS, action, CURLFORM_END); + curl_formadd (&form, &last, CURLFORM_COPYNAME, "searchType", + CURLFORM_COPYCONTENTS, action, CURLFORM_END); + } else { + perror ("No action specified."); + exit (1); + } + curl_formadd (&form, &last, CURLFORM_COPYNAME, "return", + CURLFORM_COPYCONTENTS, rettype, CURLFORM_END); + + + /* Print some debug info. + */ + if (debug) { + fprintf (stderr, "ACTION = '%s' ret = '%s'\n", action, rettype); + + curl_easy_setopt (curl, CURLOPT_VERBOSE, 1); + curl_easy_setopt (curl, CURLOPT_HEADER, 1); + } + + /* Setup the output file, if we have one. + */ + if (outfile) { + curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, vot_invWrite); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, vot_invRead); + } + + /* Setup the call to the base URL as an HTTP/POST. + headerlist = curl_slist_append (headerlist, expect); + */ + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); + + curl_easy_setopt (curl, CURLOPT_HTTPPOST, form); + curl_easy_setopt (curl, CURLOPT_URL, base_url); + + /* Execute the query. + */ + res = curl_easy_perform (curl); + + curl_slist_free_all (headerlist); + } + + curl_easy_cleanup (curl); /* always cleanup */ + if (form) + curl_formfree (form); /* then cleanup the formpost chain */ + if (outfile) + fclose (outfile); + + return (action); +} + + +/* +*/ +static void +vot_printRegionCount (char *file, int extra) +{ + FILE *fd; + int c_ivoid=1, c_sname=2, c_title=8, c_count=11, c_nrec=10, c_desc=9; + int c_corr=12; + char title[SZ_LINE], count[SZ_LINE], corr[SZ_LINE], + nrec[SZ_LINE], line[SZ_LINE], desc[SZ_LINE], *s; + + extern char *delim; + + + delim = "\t"; + if ((fd = fopen (file, "r"))) { + + fgets (line, SZ_LINE, fd); /* skip header */ + + printf ("\n"); + while (fgets (line, SZ_LINE, fd)) { + strcpy (title, ((s=vot_getTableCol(line, c_title, 1))?s:" ")); + strcpy (count, ((s=vot_getTableCol(line, c_count, 1))?s:" ")); + strcpy (nrec, ((s=vot_getTableCol(line, c_nrec, 1))?s:" ")); + if (extra) + strcpy (corr, ((s=vot_getTableCol(line, c_corr, 1))?s:" ")); + + if (verbose > 1) { + s = vot_getTableCol(line, c_sname, 1); + printf (" ShortName: %s\n", s); + + s = vot_getTableCol(line, c_ivoid, 1); + printf (" Identifier: %s\n", s); + + printf (" Title: "); ppMultiLine (title, 15, 64, 1024); + printf ("\n"); + + strcpy (desc, ((s=vot_getTableCol(line, c_desc, 1))?s:" ")); + printf (" Description: "); ppMultiLine (desc, 15, 64, 1024); + printf ("\n"); + + printf (" Count: %s of %s \n", count, nrec); + + if (extra) + printf (" Corr: %s\n", corr); + printf ("-------------------------------------\n"); + + } else { + s = vot_getTableCol(line, c_ivoid, 1); + printf (" %-20.20s %4s %s ", s, count, "C"); + + s = (vot_getTableCol (line, c_title, 1))?s:" "; + ppMultiLine (s, 35, 45, 1024); + if (extra) + printf (" (Corr=%s)", corr); + printf (" (NRec=%s)\n", nrec); + } + + bzero (line, SZ_LINE); + } + + } else { + fprintf (stderr, "Cannot open votable '%s'\n", file); + exit (1); + } +} + + +/* +*/ +static void +vot_printMatchCount (char *file) +{ + FILE *fd; + int nrows = 0; + char line[SZ_LINE]; + + + if ((fd = fopen (file, "r"))) { + + fgets (line, SZ_LINE, fd); /* skip header */ + + printf ("\n"); + while (fgets (line, SZ_LINE, fd)) + nrows++; + } + + if (verbose > 1) { + printf (" ShortName: %s\n", svcList->name); + printf (" Identifier: %s\n", svcList->identifier); + printf (" Title: "); + ppMultiLine (svcList->title, 15, 64, 1024); + printf ("\n"); + printf (" Count: %d of %d objects from '%s' matched\n", + nrows, nobjects, sources); + printf ("-------------------------------------\n"); + + } else { + printf (" %-20.20s %4d %s ", + svcList->name, nrows, "C"); + ppMultiLine(svcList->title,35,45,1024); + printf ("\n"); + } +} + + + +/* Local utility functions. +*/ + +static size_t +vot_invWrite (void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + return fwrite (ptr, size, nmemb, stream); +} + +static size_t +vot_invRead (void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + return fread(ptr, size, nmemb, stream); +} + + +static char * +vot_dbl2str (double dval) +{ + static char val[SZ_LINE]; + + bzero (val, SZ_LINE); + sprintf (val, "%f", dval); + + return (val); +} + +#endif diff --git a/vendor/voclient/voapps/lib/voKML.c b/vendor/voclient/voapps/lib/voKML.c new file mode 100644 index 00000000..23fd509f --- /dev/null +++ b/vendor/voclient/voapps/lib/voKML.c @@ -0,0 +1,543 @@ +/************************************************************************ +** VOKML.C -- Utility procedures for writing Google KML files. +** +** M. Fitzpatrick, NOAO, July 2007 +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include <math.h> +#include "VOClient.h" +#include "voAppsP.h" + + +extern int format, debug, errno, extract; +extern int kml_max, kml_sample, kml_region, kml_label, kml_verbose; +extern int kml_bySvc, kml_byObj, kml_byBoth; + +extern Service *svcList; +extern Object *objList; + +void vot_initKML (FILE *fd, svcParams *pars); +void vot_printKMLPlacemark (FILE *fd, char *id, double ra, + double dec, char *line, char *acref, svcParams *pars); +void vot_mkPlaceDescr (FILE *fd, char *line, char *acref, svcParams *pars); +void vot_closeKML (FILE *fd); + +void vot_concatKML (char *fname); +void vot_concatKMLByService (FILE *fd); +void vot_concatKMLByObject (FILE *fd); +void vot_cleanKML (); +int vot_copyKMLFile (char *root, char *sname, FILE *fd); + +char *vot_getSName (char *root); +char *vot_getOName (char *root); + + + +/************************************************************************ +** INITKML -- Initialize the KML output file header. +*/ +void +vot_initKML (FILE *fd, svcParams *pars) +{ + float x = pars->ra - 180.0, /* query center coords */ + y = pars->dec; + float llx, lly, urx, ury; /* bounding region box */ + + + if (!fd) + return; + + /* Compute the bounding box, remember the cos(delta) term so the + ** box scales properly. + */ + llx = pars->ra - (pars->sr / cos(( y * M_PI / 180.0))) - 180.0, + lly = pars->dec - pars->sr, + urx = pars->ra + (pars->sr / cos(( y * M_PI / 180.0))) - 180.0, + ury = pars->dec + pars->sr; + + + fprintf (fd, "<kml xmlns=\"http://earth.google.com/kml/2.2\" "); + fprintf (fd, " hint=\"target=sky\">\n"); + fprintf (fd, "<Document>\n"); + fprintf (fd, " <Style id=\"VO-CLI-Query\">\n"); + fprintf (fd, " <BalloonStyle>\n"); + fprintf (fd, " <text><center><b>$[name]</b></center><br/>"); + fprintf (fd, "$[description]</text>\n"); + fprintf (fd, " </BalloonStyle>\n"); + fprintf (fd, " <PolyStyle>\n"); + fprintf (fd, " <color>ffffffff</color><fill>0</fill>\n"); + fprintf (fd, " </PolyStyle>\n"); + fprintf (fd, " </Style>\n"); + fprintf (fd, " <Placemark>\n"); + fprintf (fd, " <visibility>1</visibility>\n"); + fprintf (fd, " <flyToView>1</flyToView>\n"); + if (pars->oname[0]) + fprintf (fd, " <name>%s</name>\n", pars->oname); + else + fprintf (fd, " <name>Query Center</name>\n"); + + fprintf (fd, " <description>\n"); + fprintf (fd, " <![CDATA[VO-CLI Query parameters:\n"); + fprintf (fd, " <table>\n"); + fprintf (fd, " <tr><td><b>Service Name:</b></td><td>%s</td></tr>\n", + pars->name); + fprintf (fd, " <tr><td><b>Object Name:</b></td><td>%s</td></tr>\n", + pars->oname); + fprintf (fd, " <tr><td><b>Right Ascension:</b></td><td>%f</td></tr>\n", + (float)pars->ra - 180.0); + fprintf (fd, " <tr><td><b>Declination:</b></td><td>%f</td></tr>\n", + (float)pars->dec); + fprintf (fd, " <tr><td><b>Size:</b> </td><td>%.2f Deg</td></tr>\n", + pars->sr); + fprintf (fd, " </tr>\n"); + fprintf (fd, " </table>\n"); + fprintf (fd, " ]]>\n"); + + fprintf (fd, " </description>\n"); + fprintf (fd, " <styleUrl>#VO-CLI-Query</styleUrl>\n"); + fprintf (fd, " <Point><coordinates>%f,%f,0</coordinates></Point>\n", + x, y); + + + if (kml_region) { + fprintf (fd, " <Polygon><outerBoundaryIs><LinearRing>\n"); + fprintf (fd, " <fill>0</fill>\n"); + fprintf (fd, " <coordinates>\n"); + fprintf (fd, " %f,%f,0\n", llx, lly); + fprintf (fd, " %f,%f,0\n", llx, ury); + fprintf (fd, " %f,%f,0\n", urx, ury); + fprintf (fd, " %f,%f,0\n", urx, lly); + fprintf (fd, " %f,%f,0\n", llx, lly); + fprintf (fd, " </coordinates>\n"); + fprintf (fd, " </LinearRing></outerBoundaryIs></Polygon>\n"); + } + fprintf (fd, " </Placemark>\n"); +} + + +/************************************************************************ +** PRINTKMLPLACEMARK -- Write a placemark for the given point to the KML +** file. +*/ +void +vot_printKMLPlacemark (FILE *fd, char *id, double ra, double dec, + char *line, char *acref, svcParams *pars) +{ + double x = ra - 180.0, /* Neet to convert to lat/lon */ + y = dec; + + if (!fd) + return; + + fprintf (fd, " <Placemark>\n"); + if (kml_label) + fprintf (fd, " <name>%s</name>\n", id); + + fprintf (fd, " <styleUrl>#randomIcon</styleUrl>\n"); + + if (kml_verbose) { + fprintf (fd, " <description>\n"); + vot_mkPlaceDescr (fd, line, acref, pars); + fprintf (fd, " </description>\n"); + } + + fprintf (fd, " <Point> <coordinates>%f,%f,0</coordinates> </Point>\n", + x, y); + fprintf (fd, " </Placemark>\n"); +} + + +/************************************************************************ +** MKPLACEDESCR -- Make a placemark description from the query result. +** We assume the 'line' is a header line and a data row; use this to make +** a keyw/value table +*/ +void +vot_mkPlaceDescr (FILE *fd, char *line, char *acref, svcParams *pars) +{ + char *ip, *hp, *dp, *vp, delim, val[SZ_LINE]; + extern char *toSexa (double pos); + + + if (!fd || !line) + return; + + for (dp=line; *dp != '\n'; dp++) /* get the data line */ + ; + dp++; + hp = line; /* get the header line */ + + + delim = ((format == F_CSV) ? ',' : + ((format == F_TSV) ? '\t' : + ((format == F_ASCII) ? ' ' : ','))); + + + fprintf (fd, "<![CDATA["); + fprintf (fd, "<font size=\"+1\" color=\"#a00\">"); + fprintf (fd, "<b>Resource: %s ", pars->name); + fprintf (fd, "Object: %s \n", pars->oname); + fprintf (fd, "RA: %s \n", toSexa(pars->ra / 15.0)); + fprintf (fd, "Dec: %s</b>\n", toSexa(pars->dec)); + fprintf (fd, "</font>\n"); + fprintf (fd, "<table border=\"1\" height=\"20\">\n"); + fprintf (fd, "<tr>"); + + for (ip=hp; *ip; ) { + bzero (val, SZ_LINE); + for (vp=val; *ip && *ip != '\n' && *ip != delim; ) + *vp++ = *ip++; + fprintf (fd, "<th>%s</th>", val); + if (!*ip || *ip == '\n') + break; + else if (*ip) + ip++; + } + + fprintf (fd, "\n</tr><tr>\n"); + + for (ip=dp; *ip; ) { + bzero (val, SZ_LINE); + for (vp=val; *ip && *ip != delim; ) + *vp++ = *ip++; + ip++; + fprintf (fd, "<td>%s</td>", val); + } + + fprintf (fd, "</tr></table>\n"); + + if (acref[0] && (strstr(line,"image/g") || strstr(line,"image/j"))) { + fprintf (fd, "<hr noshade=\"5\"><font size=\"+1\">"); + fprintf (fd, "Preview Image</font><br>\n"); + fprintf (fd, "<img src=\"%s\" ", acref); + fprintf (fd, "width=\"300\" height=\"300\">\n"); + } else if (acref[0] && (strstr(line,"image/fits"))) { + fprintf (fd, "<hr noshade=\"5\"><font size=\"+1\">"); + fprintf (fd, "Preview Image Not Available</font><br>\n"); + } + + + fprintf (fd, "]]>\n"); +} + + +/************************************************************************ +** CLOSEKML -- Close the KML output file. +*/ +void +vot_closeKML (FILE *fd) +{ + if (!fd) + return; + + fprintf (fd, "</Document>\n</kml>\n"); + fclose (fd); +} + + +/************************************************************************ +** CONCATKML -- Concatenate the KML file generated by the query into a +** single, hierarchical document grouped either by the service, the +** object/position (default), or both. +*/ +void +vot_concatKML (char *fname) +{ + FILE *fd = (FILE *) NULL; + extern int nservices, nobjects; + + + if (fname[0] == '-') + fd = stdout; + else if ((fd = fopen (fname, "w+")) == (FILE *) NULL) { + fprintf (stderr, "ERROR: Cannot open KML file: '%s'\n", fname); + return; + } + + /* Write the preamble to the file. + */ + fprintf (fd, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); + fprintf (fd, "<kml xmlns=\"http://earth.google.com/kml/2.2\" "); + fprintf (fd, " hint=\"target=sky\">\n"), + fprintf (fd, "<Folder id=\"Root\">\n"); + + fprintf (fd, " <Style id=\"randomIcon\">\n"); + fprintf (fd, " <IconStyle>\n"); + fprintf (fd, " <color>ffffffff</color>\n"); + fprintf (fd, " <colorMode>random</colorMode>\n"); + fprintf (fd, " <scale>1.2</scale>\n"); + fprintf (fd, " <Icon>\n"); + fprintf (fd, + " <href>http://maps.google.com/mapfiles/kml/paddle/ylw-blank.png</href>\n"); + fprintf (fd, " </Icon>\n"); + fprintf (fd, " </IconStyle>\n"); + fprintf (fd, " </Style>\n"); + fprintf (fd, " <open>1</open>\n"); + + if (nservices > 1 && nobjects > 1) { + if (kml_byObj) { + fprintf (stderr, "concat by Object\n"); + vot_concatKMLByObject (fd); + + } else if (kml_bySvc) { + vot_concatKMLByService (fd); + + } else if (kml_byBoth) { + fprintf (fd, " <Folder id=\"byObj\">\n"); + fprintf (fd, " <name>By Object</name>\n"); + fprintf (fd, " <open>0</open>\n"); + vot_concatKMLByObject (fd); + fprintf (fd, " </Folder>\n"); + + fprintf (fd, " <Folder id=\"bySvc\">\n"); + fprintf (fd, " <name>By Service</name>\n"); + fprintf (fd, " <open>0</open>\n"); + vot_concatKMLByService (fd); + fprintf (fd, " </Folder>\n"); + } + + /* Clean up the intermediate files if needed. + */ + if (format & F_KML || (extract & EX_KML && extract & EX_COLLECT)) + vot_cleanKML (); + } + + /* Write the end of the file to close it. + */ + fprintf (fd, "\n</Folder>\n</kml>\n"); + + /* Close the file descriptors. + */ + if (fd != stdout) + fclose (fd); +} + + +/************************************************************************ +** CONCATKMLBYOBJECT -- Concatenate the KML files for the query grouped +** by the object/position +*/ +void +vot_concatKMLByObject (FILE *fd) +{ + Service *svc = svcList; /* the service list */ + Proc *proc; /* process list in each service */ + Proc *ps; + char sname[SZ_FNAME], + oname[SZ_FNAME], + obj[SZ_FNAME]; + + + /* Loop over the "query matrix" by object. The process table will + ** have the same objects for each resource so we can use with the + ** first service's list of objects/positions. + */ + for (proc=svcList->proc; proc; proc=proc->next) { + bzero (oname, SZ_FNAME); + strcpy (oname, vot_getOName (proc->root)); + + fprintf (fd, " <Folder id=\"o_%s\">\n", oname); + fprintf (fd, " <name>%s</name>\n", oname); + fprintf (fd, " <open>0</open>\n"); + + /* Go through the list of services to find this object. This is + ** known to be somewhat inefficient for the moment, but we don't + ** expect the query matrix to be large, and if it is this is still + ** a small overhead compared to the queries. + */ + for (svc=svcList; svc; svc=svc->next) { + + for (ps=svc->proc; ps; ps=ps->next) { + bzero (obj, SZ_FNAME); + strcpy (obj, vot_getOName (ps->root)); + + if (strcmp (oname, obj) == 0) { + bzero (sname, SZ_FNAME); + strcpy (sname, vot_getSName (svc->proc->root)); + + if (debug) { + fprintf (stderr, "\t\t%s.%s\t%s\n", + oname, sname, ps->root); + } + + /* At this point we have the following: + ** + ** oname - name of object we using to group + ** sname - name of the service we're processing + ** ps->root - name of root file associated w/ result + ** + ** The job now is simply to concatenate any KML file onto + ** the final output. + */ + + vot_copyKMLFile (ps->root, sname, fd); + break; + } + } + } + fprintf (fd, " </Folder>\n"); + } + + return; +} + + +/************************************************************************ +** CONCATKMLBYSERVICE -- Concatenate the KML files for the query grouped +** by the data service. +*/ +void +vot_concatKMLByService (FILE *fd) +{ + Service *svc = svcList; /* the service list */ + Proc *proc; /* process list in each service */ + char sname[SZ_FNAME]; + char oname[SZ_FNAME]; + + + for (svc=svcList; svc; svc=svc->next) { + + bzero (sname, SZ_FNAME); + strcpy (sname, vot_getSName (svc->proc->root)); + + fprintf (fd, " <Folder id=\"o_%s\">\n", sname); + fprintf (fd, " <name>%s</name>\n", sname); + fprintf (fd, " <open>0</open>\n"); + + for (proc=svc->proc; proc; proc=proc->next) { + bzero (oname, SZ_FNAME); + strcpy (oname, vot_getOName (proc->root)); + vot_copyKMLFile (proc->root, oname, fd); + } + + fprintf (fd, " </Folder>\n"); + } + + return; +} + + + +/************************************************************************ +** Utility routines to extract bits from the root filename. +*/ +char * +vot_getSName (char *root) +{ + char *ip, *op; + static char val[SZ_FNAME]; + + bzero (val, SZ_FNAME); + for (ip=root, op=val; *ip && *ip != '_'; ) + *op++ = *ip++; + + return (val); +} + +char * +vot_getOName (char *root) +{ + char *ip, *op; + static char val[SZ_FNAME]; + + bzero (val, SZ_FNAME); + + /* skip service name and type. + */ + for (ip=root; *ip && *ip != '_'; ) ip++; ip++; + for ( ; *ip && *ip != '_'; ) ip++; ip++; + + /* get object name */ + for (op=val; *ip && *ip != '.' && *ip != '_'; ) + *op++ = *ip++; + + return (val); +} + + +/************************************************************************ +** COPYKMLFILE -- Copy a KML file to the output file descriptor for inclusion +** in a grander hierarchy. To do this we copy out only the inner part of +** the <Document> in a single file. +*/ +int +vot_copyKMLFile (char *root, char *name, FILE *fd) +{ + char line[4096], fname[SZ_FNAME]; + FILE *ifd; + + + bzero (fname, SZ_FNAME); + sprintf (fname, "%s.kml", root); + + if (access (fname, R_OK) == 0) { + if ((ifd = fopen (fname, "r")) == (FILE *) NULL) { + fprintf (stderr, "Warning: Cannot open file '%s'\n", fname); + return (ERR); + } + } else { + /* A missing file just means there's no data, but we want to + ** reflect that in the file as an empty folder. + */ + return (OK); + } + + fprintf (fd, " <Folder id=\"s_%s\">\n", name); + fprintf (fd, " <name>%s</name>\n", name); + fprintf (fd, " <open>0</open>\n"); + fprintf (fd, " <flyToView>1</flyToView>\n"); + fprintf (fd, " <styleUrl>#randomIcon</styleUrl>\n"); + + /* Skip ahead to the start of the part we're interested in. + */ + bzero (line, 4096); + while (fgets (line, 4096, ifd)) { + if (strstr (line, "<Document>")) + break; + bzero (line, 4096); + } + + /* (Slow) Copy the file until the end of the Document. + */ + bzero (line, 4096); + while (fgets (line, 4096, ifd)) { + if (strstr (line, "</Document>")) + break; + fprintf (fd, "%s", line); + bzero (line, 4096); + } + + fprintf (fd, " </Folder>\n"); + + fclose (ifd); + return (OK); +} + + +/************************************************************************ +** CLEANKML -- Clean up the intermediate KML files. +*/ +void +vot_cleanKML () +{ + Service *svc = svcList; /* the service list */ + Proc *proc; /* process list in each service */ + char fname[SZ_FNAME]; + + + for (svc=svcList; svc; svc=svc->next) { + for (proc=svc->proc; proc; proc=proc->next) { + bzero (fname, SZ_FNAME); + sprintf (fname, "%s.kml", proc->root); + unlink (fname); + + bzero (fname, SZ_FNAME); + sprintf (fname, "%s.csv", proc->root); + unlink (fname); + } + } +} diff --git a/vendor/voclient/voapps/lib/voLog.c b/vendor/voclient/voapps/lib/voLog.c new file mode 100644 index 00000000..269340d5 --- /dev/null +++ b/vendor/voclient/voapps/lib/voLog.c @@ -0,0 +1,225 @@ +/** + * @file voLog.c + * @author Mike Fitzpatrick, NOAO + * @date 6/10/09 + * + * @brief VOApps logging interface. + */ +/*****************************************************************************/ + + +#include <stdio.h> +#include <fcntl.h> +#include <signal.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <pthread.h> +#include <errno.h> + +#include "voApps.h" +#include "voAppsP.h" + + +#define SZ_FMTSPEC 25 /* max size single format spec */ +#define SZ_ARGVAL 128 +#define EOS 0 + +#define TY_INT 0 /* the only types we support */ +#define TY_DOUBLE 1 +#define TY_CHAR 2 + + +/* Public methods. +*/ +void vo_encodeString (char *buf, char *format, va_list *argp); +char *vo_doarg (va_list **argp, int dtype); +char *vo_logtime (); + +static char argVal[SZ_ARGVAL]; + + + +/** + * VO_APPLOG -- VOApp message logger. + * + * @fn vo_appLog (char *format, ...) + * + * @brief VOApps message logger. + * @param fd logging file descriptor + * @param format message format string + * @return nothing + */ +void +vo_appLog (FILE *fd, char *format, ...) +{ + int len; + char *buf; + va_list argp; + + + va_start (argp, format); /* encode as a single string */ + buf = calloc (1, (4 * SZ_LINE) ); + vo_encodeString (buf, format, &argp); + va_end (argp); + + len = strlen (buf); /* ensure a newline */ + if (strcmp ("\n", &buf[len-1])) + strcat (buf, "\n"); + + if (fd) + fprintf (fd, "%s %s", vo_logtime(), buf); + + free ((void *) buf); +} + + +/** + * VO_ENCODESTRING -- Process the format to the output file, taking arguments + * from the list pointed to by argp as % format specs are encountered in + * the input. + * + * @fn vo_encodeString (char *buf, char *format, va_list *argp) + * + * @param buf formatted output buffer + * @param format format string + * @param argp variable-length arguments + * @return + */ +void +vo_encodeString (char *buf, char *format, va_list *argp) +{ + register int ch; /* next format char reference */ + char formspec[SZ_FMTSPEC]; /* copy of single format spec */ + char *fsp; /* pointer into formspec */ + char cbuf[10]; + int done; /* one when at end of a format */ + int nch = SZ_LINE; /* one when at end of a format */ + + + while ((ch = *format++) && nch > 0) { + if (ch == '%') { + fsp = formspec; + *fsp++ = ch; + done = 0; + + while (!done) { + ch = *fsp++ = *format++; + + switch (ch) { + case EOS: + --format; + done++; + break; + + case 'l': + fsp--; /* arg size modifier; ignored for now */ + break; + + case 'b': /* nonstandard UNIX */ + case 'c': + case 'd': + case 'o': + case 'x': + case 'u': + *fsp = EOS; + strcat (buf, vo_doarg (&argp, TY_INT)); + done++; + break; + + case 'E': /* ANSI emulation */ + *(fsp-1) = 'e'; + goto rval; + case 'G': /* ANSI emulation */ + *(fsp-1) = 'g'; + goto rval; + + case 'e': + case 'f': + case 'g': +rval: + *fsp = EOS; + strcat (buf, vo_doarg (&argp, TY_DOUBLE)); + done++; + break; + + case 's': + *fsp = EOS; + strcat (buf, vo_doarg (&argp, TY_CHAR)); + done++; + break; + } + } + + } else { + memset (cbuf, 0, 10); + sprintf (cbuf, "%c", ch); + strcat (buf, cbuf); + } + + nch = SZ_LINE - strlen (buf); /* prevent overflow */ + } +} + + +/** + * VO_DOARG -- Encode a single argument acording to the data type. + * + * @fn static char *vo_doarg (va_list **argp, int dtype) + * + * @param argp argument list + * @param dtype data type + * + */ +char * +vo_doarg (va_list **argp, int dtype) +{ + int ival; + double dval; + char *cptr; + + + memset (argVal, 0, SZ_ARGVAL); + + /* Pass the data value to be encoded, bump argument pointer by the + ** size of the data object. If there is no data value the case + ** is a no-op. + */ + switch (dtype) { + case TY_INT: + ival = va_arg ((**argp), int); + sprintf (argVal, "%d", ival); + break; + case TY_DOUBLE: + dval = va_arg ((**argp), double); + sprintf (argVal, "%g", dval); + break; + case TY_CHAR: + cptr = va_arg ((**argp), char *); + sprintf (argVal, "%s", cptr); + break; + } + + return (argVal); +} + + + +/** + * LOGTIME - Generate a time string for the log. + * + * @fn static char *vo_logtime() + */ +char * +vo_logtime () +{ + time_t t = time (NULL); + struct tm *tm = gmtime (&t); + static char tstr[128]; + + memset (tstr, 0, 128); + strftime (tstr, 128, "%m%d %T", tm); + + return (tstr); +} diff --git a/vendor/voclient/voapps/lib/voObj.c b/vendor/voclient/voapps/lib/voObj.c new file mode 100644 index 00000000..5915fb7e --- /dev/null +++ b/vendor/voclient/voapps/lib/voObj.c @@ -0,0 +1,761 @@ +/**************************************************************************** +** VOARGS.C -- Procedures for commandline argument handling. We also do +** some of the heavy lifting for registry and object resolution. +** +** M. Fitzpatrick, NOAO, June 2007 +*/ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#include <unistd.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#include "VOClient.h" +#include "votParse.h" +#include "voAppsP.h" + + +#define OBJ_DEBUG 0 /* local debug options */ + + +extern int nobjects, nservices; +extern int verbose, quiet, debug, errno, force_svc, meta; +extern int all_data, use_name, all_named, url_proc, obj_list; +extern int force_read, table_hskip, table_nlines, table_sample; +extern char *typestr, *bpass, *delim, *cols, *ecols, *output; + +extern Object *objList, *objTail; + +int objIndex = 0; + +int ra_col = 1; /* input table RA column default */ +int ra_span = 1; /* input table RA column span */ +int dec_col = 2; /* input table Dec column default */ +int dec_span = 1; /* input table Dec column span */ +int id_col = 0; /* input table ID column (0 => none) */ +int id_span = 0; /* input table ID column span */ + + +int vot_parseObjectList (char *list, int isCmdLine); +int vot_printObjectList (FILE *fd); +void vot_freeObjectList (void); +void vot_readObjFile (char *fname); + +static int vot_objectResolver (char *idlist, int nwords, int isCmdLine); +static int vot_loadVOTable (char *fname); +static int vot_countWords (FILE *fd); +static int vot_parseCmdLineObject (char *idlist); +static void vot_getColumns (); + +static char *vot_parseTableLine (char *idlist, int nwords, + double *ra, double *dec); + +extern char *vot_copyStdin (void); +extern char *vot_getTableCol (char *line, int col, int span); +extern char *toSexa (double val); +extern char *strcasestr (); +extern char *vot_normalize (char *str); +extern char *vot_normalizeCoord (char *coord); +extern char *vot_mktemp (char *root); +extern char *vot_getTableCell (int vot, int row, int col); + +extern int isVOTable (char *fname); +extern void vot_skipHdr (FILE *fd); + + +/* Utility procedures. +*/ +extern int isSexagesimal (char *str); +extern int isDecimal (char *str); +extern float sexa (char *s); +extern char *toSexa (double pos); +extern char *toSexaTime (int nsec); + + + + +/**************************************************************************** +** Parse a string containing object names or positions. The string may be a +** single object, a comma-delimited list, or the name of a file containing +** the same. Additionally, values positions specified as either sexagesimal +** or decimal RA/Dec (assumed J2000). Positions may be whitespace or +** comma-delimited. +*/ +int +vot_parseObjectList (char *list, int isCmdLine) +{ + FILE *fd; + char line[SZ_LINE]; + int i, nl = 1, nwords; + + + if (access (list, R_OK) == 0) { + + if (isVOTable (list)) { + nl = vot_loadVOTable (list); + return (0); + } + + /* Process the file contents. + */ + if ((fd = fopen (list, "r")) == (FILE *) NULL) { + fprintf (stderr, "ERROR: Cannot open file '%s'\n", list); + return (1); + } + + /* Count the number of words (tokens) on each line of the list. + */ + vot_skipHdr (fd); + if ((nwords = vot_countWords (fd)) < 0 && !force_read) { + fprintf (stderr, + "ERROR: Can't parse object/position table '%s' ", list); + fprintf (stderr, "(Variable number of columns).\n"); + fclose (fd); + exit (1); + } + + /* Parse the column description so we can properly read a table. + */ + vot_getColumns (); + vot_skipHdr (fd); /* prepare */ + + while (fgets (line, SZ_LINE, fd)) { /* do it */ + + /* Resolve the object name. + */ + vot_objectResolver (line, nwords, FALSE); + + /* Enforce the max number of lines to read. + */ + if (table_nlines > 0 && nl >= table_nlines) + break; + else + nl++; + + /* Enforce the table sampling. + */ + if (table_sample > 1) { + for (i=1; i < table_sample; i++) { + if (fgets (line, SZ_LINE, fd) == (char *)NULL) + break; + } + } + } + + fclose (fd); + use_name = 0; + + } else + vot_objectResolver (list, 1, isCmdLine); + + + if (debug) + vot_printObjectList (stderr); + if (obj_list) { + FILE *fd; + char listfile[SZ_FNAME]; + + memset (listfile, 0, SZ_FNAME); + sprintf (listfile, "%s.objects", output); + if ((fd = fopen (listfile, "w+")) != (FILE *) NULL) { + vot_printObjectList (fd); + fclose (fd); + } + } + + return (0); +} + + +/**************************************************************************** +** LOADVOTABLE -- Read a VOTable and load the Object list with its contents. +*/ +static int +vot_loadVOTable (char *fname) +{ + int vot = 0, i; + int nr, nc, nresults = 0, nwords = 0; + int c_ra, c_dec, c_id; + char ra[SZ_FNAME], dec[SZ_FNAME], id[SZ_FNAME]; + char buf[SZ_LINE]; + + + if ((vot = vot_openVOTABLE (fname)) ) { + + int res, tab, data, tdata; + + res = vot_getRESOURCE (vot); /* get handles */ + if ((tab = vot_getTABLE (res)) <= 0) + return (-1); + if ((data = vot_getDATA (tab)) <= 0) + return (-1); + if ((tdata = vot_getTABLEDATA (data)) <= 0) + return (-1); + nr = vot_getNRows (tdata); + nc = vot_getNCols (tdata); + + c_ra = vot_colByUCD (tab, "POS_EQ_RA_MAIN", "pos.eq.ra"); + c_dec = vot_colByUCD (tab, "POS_EQ_DEC_MAIN", "pos.eq.dec"); + c_id = vot_colByUCD (tab, "ID_MAIN", "meta.id"); + if (OBJ_DEBUG) + fprintf (stderr, "%d rows x %d cols ra:%d dec:%d id:%d\n", + nr, nc, c_ra, c_dec, c_id); + + for (i=0; i < nr; i++) { + bzero (ra, SZ_FNAME); + strcpy (ra, vot_getTableCell(vot, i, c_ra)); + + bzero (dec, SZ_FNAME); + strcpy (dec, vot_getTableCell(vot, i, c_dec)); + + if (c_id >= 0) { + bzero (id, SZ_FNAME); + + strcpy (id, vot_getTableCell(vot, i, c_id)); + nwords = 3; + } else + nwords = 2; + + if (OBJ_DEBUG) + fprintf (stderr, "%d: ra:%s dec:%s id:%s\n", i, ra, dec, id); + + /* Build up a fake line of input containing the RA/Dec/ID on + ** a line. We do it this way so the normalize() procedures + ** don't overwrite a string. + */ + bzero (buf, SZ_LINE); + strcpy (buf, vot_normalizeCoord (ra)); + strcat (buf, " "); + strcat (buf, vot_normalizeCoord (dec)); + strcat (buf, " "); + strcat (buf, (c_id >= 0 ? vot_normalize (id) : "")); + + if (OBJ_DEBUG) fprintf (stderr, "resolve buf = '%s'\n", buf); + + vot_objectResolver (buf, nwords, FALSE); + nresults++; + } + } else { + fprintf (stderr, "Cannot open votable '%s'\n", fname); + exit (1); + } + + if (vot > 0) + vot_closeVOTABLE (vot); + + return (nresults); +} + + +/**************************************************************************** +** GETCOLUMNS -- Parse the column description parameter to figure out how +** to read a table properly. We only allow for ra/dec/id and the default is +** that the 'id' column is not present (col=0). Otherwise, columns are +** given as a comma-delimited, one-indexed list of integers. A range may +** be specified to span multiple columns for reading e.g. multi-word ID tags +** or whitespace-delimited sexagesimal. +*/ + +static void +vot_getColumns () +{ + char *ip = cols, *op, ra_c[SZ_FNAME], dec_c[SZ_FNAME], id_c[SZ_FNAME]; + int first, last; + + + ip = (ecols ? ecols : cols); + + bzero (ra_c, SZ_FNAME); /* get RA column */ + for (op=ra_c; *ip && *ip != ','; ) + *op++ = *ip++; + if (*ip) ip++; + + bzero (dec_c, SZ_FNAME); /* get Dec column */ + for (op=dec_c; *ip && *ip != ','; ) + *op++ = *ip++; + if (*ip) ip++; + + bzero (id_c, SZ_FNAME); /* get ID column */ + if (*ip) { + for (op=id_c; *ip; ) + *op++ = *ip++; + } + + + /* Now parse each of the column strings and create the col/span values. + */ + if ((ip = strchr (ra_c, (int)'-'))) { /* set RA columns */ + *ip++ = '\0'; + first = ra_col = atoi (ra_c); + last = atoi (ip); + ra_span = (last - first + 1); + } else { + ra_col = atoi (ra_c); + ra_span = 1; + } + + if ((ip = strchr (dec_c, (int)'-'))) { /* set Dec columns */ + *ip++ = '\0'; + first = dec_col = atoi (dec_c); + last = atoi (ip); + dec_span = (last - first + 1); + } else { + dec_col = atoi (dec_c); + dec_span = 1; + } + + if (id_c[0]) { + if ((ip = strchr (id_c, (int)'-'))) { /* set ID columns */ + *ip++ = '\0'; + first = id_col = atoi (id_c); + last = atoi (ip); + id_span = (last - first + 1); + } else { + id_col = atoi (id_c); + id_span = 1; + } + } + + if (OBJ_DEBUG) { + fprintf (stderr, "ra_c='%s' dec_c='%s' id_c='%s'\n",ra_c,dec_c,id_c); + fprintf (stderr, " ra: col=%d span=%d\n", ra_col, ra_span); + fprintf (stderr, " dec: col=%d span=%d\n", dec_col, dec_span); + fprintf (stderr, " id: col=%d span=%d\n", id_col, id_span); + } +} + + +/**************************************************************************** +** Free the service list and reset the counter. +*/ +void +vot_freeObjectList () +{ + Object *cur, *next; + + for (cur=objList; cur; cur=next) { + next = cur->next; + if (cur) + free ((void *) cur); + } + nobjects = 0; + objList = objTail = (Object *) NULL; +} + + +/**************************************************************************** +** Resolve a service name/list to the proper service URL and store the +** result in the 'objList' global which we assume is declared in the caller. +*/ +static int +vot_objectResolver (char *idlist, int nwords, int isCmdLine) +{ + char *id = (char *)NULL, *name = (char *)NULL, *ip; + double ra, dec; + Object *obj; + Sesame sesame; + + + /* The task was originally written to allow comma-delimieted objects + ** to be specified on the command line, or as multiple objects in a + ** file. To preserve this functionality we'll call the old code when + ** given a command-line argument, otherwise we'll parse the file + ** according to more strict rules below. + */ + if (isCmdLine) { + return ((int)vot_parseCmdLineObject (idlist)); + } + + + /* If there is only a single item on the line then it can only be either + ** the name of a file to be processed, or an object to be resolved. + */ + if (nwords == 1) { + + if (access (idlist, R_OK) == 0) { /* file */ + vot_parseObjectList (idlist, FALSE); + return (OK); + + } else { /* resolve name */ + /* Clobber the newline and do a poor-man's URL encoding of + ** embedded spaces. + */ + for (ip=idlist; *ip; ip++) { + /* preserve spaces..... */ + if (*ip == ' ') *ip = '+'; + if (*ip == '\n') *ip = '\0'; + } + + sesame = voc_nameResolver (idlist); + ra = voc_resolverRA (sesame); + dec = voc_resolverDEC (sesame); + name = idlist; + + /* If the positions are zero, make sure the errs are also zero + ** before deciding that the resolver failed. We won't bother + ** with this object but will print a warning. + */ + if (ra == 0.0 && dec == 0.0) { + if (voc_resolverRAErr (sesame) == 0.0 && + voc_resolverDECErr (sesame) == 0.0) { + fprintf (stderr, + "Warning: Cannot resolve '%s'....skipping\n", name); + return (ERR); + } + } else + all_named = 1; + } + + if (verbose && id && !quiet) { + fprintf (stderr,"# Resolver: %-20s -> ", (name ? name : "(none)")); + fprintf (stderr," %11.11s", toSexa(ra)); + fprintf (stderr," %12.12s", toSexa(dec)); + fprintf (stderr,"\n"); + } + + } else { + + /* The line represents a table of some kind. In the simplest form + ** this could just be the RA/Dec in a 2-column list but it could + ** also be a CSV file where the 'cols' parameter tell us where to + ** find the values. The 'id' string may be optional in the table, + ** if not specified we'll make something up. + */ + id = vot_parseTableLine (idlist, nwords, &ra, &dec); + + if (verbose > 1&& id && !quiet) { + fprintf (stderr,"# Resolver: %-16.16s", (id ? id : "(none)")); + fprintf (stderr," %11.11s", toSexa(ra)); + fprintf (stderr," %12.12s", toSexa(dec)); + fprintf (stderr,"\n"); + } + + if (OBJ_DEBUG) + fprintf (stderr, "ra=%f dec=%f id='%s'\n", ra, dec, (id?id:"null")); + } + + /* Save results in the object list. + */ + obj = (Object *)calloc (1,sizeof(Object)); + if (!objList) + objList = objTail = obj; + else + objTail->next = (Object *)obj; + + strcpy (obj->name, (name ? name : "")); + strcpy (obj->id, (id ? id : "")); + obj->ra = ra; + obj->dec = dec; + obj->index = objIndex++; + + objTail = obj; + + + return (OK); +} + + +/**************************************************************************** +** PARSETABLELINE -- Parse a line of table input to extract the values for +** the given ra/dec/id columns. Values that span multiple columns are +** concatenated to a single space-delimited string. +*/ +static char * +vot_parseTableLine (char *idlist, int nwords, double *ra, double *dec) +{ + char *id = (char *) NULL, *sra = (char *) NULL, *sdec = (char *) NULL; + + + + if (ecols == (char *)NULL && nwords == 3) { + /* No user-specified columns, see if we can figure it out. + */ + char *c1 = calloc (1, SZ_LINE); + char *c2 = calloc (1, SZ_LINE); + char *c3 = calloc (1, SZ_LINE); + + strcpy (c1, vot_getTableCol (idlist, 1, 1)); + strcpy (c2, vot_getTableCol (idlist, 2, 1)); + strcpy (c3, vot_getTableCol (idlist, 3, 1)); + + if ( (strchr(c1,(int)'.') && strchr(c2,(int)'.')) || + (strchr(c1,(int)':') && strchr(c2,(int)':')) ) { + + /* ID is column 3 */ + sra = strdup (vot_normalizeCoord (c1)); + sdec = strdup (vot_normalizeCoord (c2)); + id = vot_normalize (c3); + + } else if ( (strchr(c2,(int)'.') && strchr(c3,(int)'.')) || + (strchr(c2,(int)':') && strchr(c3,(int)':')) ) { + + /* ID is column 1 */ + id = vot_normalize (c1); + sra = strdup (vot_normalizeCoord (c2)); + sdec = strdup (vot_normalizeCoord (c3)); + + } else { + fprintf (stderr, "ERROR: Unable to parse table colummns\n"); + *ra = *dec = 0.0; + free (c1); free (c2); free (c3); + return ((char *)NULL); + } + *ra = (strchr (sra, (int)':') ? (sexa (sra) * 15.) : atof (sra)); + *dec = (strchr (sdec, (int)':') ? sexa (sdec) : atof (sdec)); + + free (c1); free (c2); free (c3); + free (sra); free (sdec); + + } else { + sra = vot_normalizeCoord (vot_getTableCol (idlist, ra_col, ra_span)); + *ra = (strchr (sra, (int)':') ? (sexa (sra) * 15.) : atof (sra)); + + sdec = vot_normalizeCoord (vot_getTableCol (idlist, dec_col, dec_span)); + *dec = (strchr (sdec, (int)':') ? sexa (sdec) : atof (sdec)); + + if (nwords == 3 && id_col == 0) + id = vot_normalize (vot_getTableCol (idlist, 3, 1)); + else + id = vot_normalize (vot_getTableCol (idlist, id_col, id_span)); + } + + return ((char *) id); +} + + +/**************************************************************************** +** Resolve a service name/list to the proper service URL and store the +** result in the 'objList' global which we assume is declared in the caller. +*/ +static int +vot_parseCmdLineObject (char *idlist) +{ + char *ip, *op, *id, opos[SZ_LINE]; + double ra, dec; + Object *obj; + Sesame sesame; + extern double sr; + + + /* Resolve the (list) of object names/positions and add them to the + ** service list to be processed. + */ + ip = idlist; + while (*ip) { + + /* Break up the input list into a single ID to resolve. + */ + op = &opos[0]; + bzero (opos, SZ_LINE); + + /* We allow positions to be comma-delimited, but objects + ** list are processed individually. + */ + while (*ip && *ip != '\n') { + if (*ip == ',') { + if (isDecimal(opos) || isSexagesimal(opos)) { + *op++ = ' '; ip++; + } else { + *ip++ = '\0'; + break; + } + } else + *op++ = *ip++; + } + if (*ip && *(ip-1)) /* only advance on a position */ + ip++; + + + /* Process the name, position or file. + */ + if (access (opos, R_OK) == 0) { /* file */ + vot_parseObjectList (opos, FALSE); + continue; + + } if (isDecimal (opos)) { /* decimal */ + for (op=opos; !isspace (*op); op++) + ; + ra = atof (opos); + dec = atof (op); + id = (char *) NULL; + all_named = 0; + + } else if (isSexagesimal (opos)) { /* sexagesimal */ + for (op=opos; !isspace (*op); op++) + ; + ra = sexa (opos) * 15.0; + dec = sexa (op); + id = (char *) NULL; + all_named = 0; + + } else { /* resolve name */ + char *ip = opos; + + /* Clobber the newline and do a poor-man's URL encoding of + ** embedded spaces. + */ + for (ip=opos; *ip; ip++) { + /* preserve spaces..... */ + if (*ip == ' ') *ip = '+'; + if (*ip == '\n') *ip = '\0'; + } + + sesame = voc_nameResolver (opos); + ra = voc_resolverRA (sesame); + dec = voc_resolverDEC (sesame); + id = opos; + all_named = 1; + + /* If the positions are zero, make sure the errs are also zero + ** before deciding that the resolver failed. We won't bother + ** with this object but will print a warning. + */ + if (ra == 0.0 && dec == 0.0) { + if (voc_resolverRAErr (sesame) == 0.0 && + voc_resolverDECErr (sesame) == 0.0) { + fprintf (stderr, + "Warning: Cannot resolve '%s'....skipping\n", opos); + continue; + } + } + } + + if (verbose && id && !quiet) + fprintf (stderr,"# Resolver: %-20s -> %-10.10s %.6f %.6f (%.2f)\n", + opos, (id ? id : "(none)"), ra, dec, (float)sr); + + /* Save results in the object list. + */ + obj = (Object *)calloc (1,sizeof(Object)); + if (!objList) + objList = objTail = obj; + else + objTail->next = (Object *)obj; + + strcpy (obj->name, (id ? id : "")); + obj->ra = ra; + obj->dec = dec; + obj->index = objIndex++; + + objTail = obj; + } + + return (0); +} + + +/**************************************************************************** +** Utility routines to print and count the object list. +*/ + +int +vot_countObjectList () +{ + register int i = 0; + Object *obj = objList; + + if (!obj) + return (0); + else + while ((obj = obj->next)) i++; + + return (i+1); +} + + +int +vot_printObjectList (FILE *fd) +{ + register int i = 0; + Object *obj = objList; + + fprintf (fd, "# Objects queried: %d\n#\n", vot_countObjectList()); + fprintf (fd, "# %4s\t%-12.12s\t%11.11s\t%12.12s\n", + "Id", "Name", "RA", "Dec"); + do { + fprintf (fd, "%4d\t%-12.12s\t%11.6f\t%12.6f\n", i++, + obj->name, obj->ra, obj->dec); + } while ((obj = obj->next)); + + return (0); +} + + + +/****************************************************************************** +** COUNTWORDS -- Count the number of words (tokens) on each line of the list. +** If the number varies for each line it's likely to be a table we can't +** handle so throw an error, otherwise assume we have a single item or +** a consistent table. Allowed delimiters include whitespace, tabs, +** commas or '|'. Lines beginning with a '#' are ignored. +*/ +static int +vot_countWords (FILE *fd) +{ + char *tok, *line = (char *) NULL; + char *sep = delim, *del = (char *) NULL; + int ntok = -1, last_ntok = -1; + + line = malloc(4096); + + while (1) { + + bzero (line, 4096); /* get a line of data */ + if (fgets (line, SZ_FNAME, fd) == (char *)NULL) + break; + + if (line[0] == '#' || line[0] == '\n') /* skip comments/blank */ + continue; + + if (last_ntok < 0) { /* first line only */ + del = strpbrk (line, " \t,|"); + if (del) { + sep = calloc (1,16); + sep[0] = del[0]; + } else + sep = delim; + } + + for (ntok=0, tok=strtok(line, sep); tok; tok=strtok(NULL, sep)) { + if (tok[0] != '\n') + ntok++; + } + + if (last_ntok >= 0 && ntok != last_ntok) { + free ((void *) line); + return (-1); + } + last_ntok = ntok; + } + + rewind (fd); + free ((void *) line); + + return (ntok); +} + + +void +vot_readObjFile (char *fname) +{ + char tmpfile[SZ_FNAME]; + + + bzero (tmpfile, SZ_FNAME); + + if (strcmp (fname, "-") == 0) { /* read from stdin */ + + strcpy (tmpfile, vot_copyStdin ()); + + /* Parse the input and unlink the temp file. + */ + vot_parseObjectList (tmpfile, TRUE); + if (access (tmpfile, R_OK) == 0) + unlink (tmpfile); + + } else if (access (fname, R_OK) == 0) + vot_parseObjectList (fname, TRUE); +} diff --git a/vendor/voclient/voapps/lib/voParams.c b/vendor/voclient/voapps/lib/voParams.c new file mode 100644 index 00000000..bc6869a5 --- /dev/null +++ b/vendor/voclient/voapps/lib/voParams.c @@ -0,0 +1,189 @@ +/** + * VOPARAMS.C -- Interface to manage cmdline options or library parameters. + * + * @file voParams.c + * @author Mike Fitzpatrick + * @date 7/03/12 + * + * @brief Interface to manage cmdline options or library parameters. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <getopt.h> +#include <string.h> +#include <errno.h> +#include "voApps.h" +#include "voAppsP.h" + + +#define MAXARGS 256 +#define SZ_ARG 128 + + + +/** + * VO_PARAMINIT -- Initialize the task parameter vector. + * + * @brief Initialize the task parameter vector. + * @fn char **vo_paramInit (int argc, char *argv[]) + * + * @param argc argument count + * @param argv argument vector + * @returns modified argument vector + */ +char ** +vo_paramInit (int argc, char *argv[], char *opts, struct option long_opts[]) +{ + static char *pargv[MAXARGS], arg[SZ_ARG]; + int i, j, len = 0; + + memset (&pargv[0], 0, MAXARGS); + for (i=0; i < argc; i++) { + /* Make a local copy of the arg so we can modify it w/out side + * effects. + */ + memset (arg, 0, SZ_ARG); + strcpy (arg, argv[i]); + len = strlen (arg); + + if (arg[0] != '-') { + pargv[i] = calloc (1, strlen (arg) + 6); + if (strchr (argv[i], (int) '=')) + sprintf (pargv[i], "--%s", arg); + else if (argv[i][len-1] == '+') { + arg[len-1] = '\0'; + sprintf (pargv[i], "--%s=1", arg); + } else if (argv[i][len-1] == '-') { + arg[len-1] = '\0'; + sprintf (pargv[i], "--%s=0", arg); + } else + sprintf (pargv[i], "%s", arg); + + } else { + if (arg[0] == '-' && arg[1] != '-') { + if (arg[2] == '=') { + /* Argument is of the form '-f=bar' instead of the form + * "--foo=bar" or "--foo bar" or "foo=bar". We need to + * rewrite it to be acceptable to getopt_long(). + */ + char new[SZ_ARG]; + + memset (new, 0, SZ_ARG); + for (j=0; (char *)long_opts[j].name; j++) { + if ((int) long_opts[j].val == (int) arg[1]) { + sprintf (new, "--%s=%s",long_opts[j].name, &arg[3]); + memset (arg, 0, SZ_ARG); + strcpy (arg, new); + len = strlen (arg); + } + } + + } else if (arg[2] != '=' && strchr (arg, (int)'=')) { + fprintf (stderr, "Illegal flag '%s', skipping.\n", arg); + continue; + } + } + + pargv[i] = calloc (1, strlen (arg) + 1); + sprintf (pargv[i], "%s", arg); + } + } + +#ifdef DEBUG + for (i=0; i < argc; i++) + fprintf (stderr, "argv[%d] = '%s'\n", i, pargv[i]); +#endif + return (pargv); +} + + +/** + * VO_PARAMNEXT -- Get the next parameter value. + * + * @brief Get the next parameter value. + * @fn int vo_paramNext (char *opts, struct option long_opts[], + * int argc, char *argv[], char *optval, int *posindex) + * + * @param opts option string + * @param long_opts long options struct + * @param argc argument count + * @param argv argument vector + * @param optval optional parameter argument + * @param posindex positional parameter index (0-based) + * @returns nothing + */ +int +vo_paramNext (char *opts, struct option long_opts[], int argc, char *argv[], + char *optval, int *posindex) +{ + int ch = 0, index; + static int pos = 0, apos = 0; + + + apos++; + memset (optval, 0, SZ_FNAME); +#ifdef USE_GETOPT_LONG + ch = getopt_long (argc, argv, opts, long_opts, &index); +#else + ch = getopt_long_only (argc, argv, opts, long_opts, &index); +#endif + if (ch >= 0) { + if (ch > 0 && optarg) { + if ((strchr (optarg, (int)'=') != 0) && (optarg[0] != '-') && + (argv[apos][0] == '-' && argv[apos][1] != '-') ) { + fprintf (stderr, + "Error: invalid argument = '%s' in vot_paramNext()\n", + argv[apos]); + return (PARG_ERR); + } else { + if (optarg[0] == '-') { + // optind--; + memset (optval, 0, SZ_FNAME); + } else + strcpy (optval, optarg); + } + + } else if (ch == 0) { + *posindex = index; + if (optarg) + strcpy (optval, optarg); + } + + } else { + if (argv[optind+pos]) { + strcpy (optval, argv[optind+pos]); + *posindex = pos++; + return (-pos); + } else + return (0); + } + +#ifdef DEBUG + fprintf (stderr, "ch = %d (%c) optval='%s' optarg='%s' index=%d\n", + ch, ch, optval, optarg, index); +#endif + return (ch); +} + + +/** + * VO_PARAMFREE -- Free the allocated parameter vector. + * + * @brief Free the allocated parameter vector. + * @fn void vo_paramFree (int argc, char *argv[]) + * + * @param argc argument count + * @param argv argument vector + * @returns nothing + */ +void +vo_paramFree (int argc, char *argv[]) +{ + register int i; + + for (i=0; i < argc; i++) { + if (argv[i] && argv[i][0]) + free ((void *)argv[i]); + } +} diff --git a/vendor/voclient/voapps/lib/voRanges.c b/vendor/voclient/voapps/lib/voRanges.c new file mode 100644 index 00000000..0c1ed608 --- /dev/null +++ b/vendor/voclient/voapps/lib/voRanges.c @@ -0,0 +1,286 @@ +/****************************************************************************** +** RANGES -- Simple range-specification package to decode lists of numbers +** or ranges of the form: +** +** <start> '-' <end> [ 'x' <stride>] +** +** Sample code using this package might look like: +** +** +** #include <stdlib.h> +** #include <ctype.h> +** +** int vot_decodeRanges(char *str, int *ranges, int max_ranges,int *nvalues); +** int get_next_number (int *ranges, int number); +** +** int main (int argc, char **argv) +** { +** char *rtest[] = { "1-10,12,16", "1-7x2,12-14", +** "1,3,5,7,9-12", "1,8", +** "12-8", "12-8x-1", +** NULL }; +** int i, *ranges, max_ranges=100, nvalues=0, val; +** +** ranges = (int *) malloc (1024); +** for (i=0; rtest[i]; i++) { +** printf ("vot_decodeRanges: '%s'\n\n ", rtest[i]); +** val = vot_decodeRanges (rtest[i], ranges, max_ranges, &nvalues); +** for (val=0; (val = get_next_number (ranges, val)) > 0; ) +** printf (" %d ", val); +** } +** } +** +** Assumes ranges are positive and always increasing, i.e. a range "3-1" +** will not return (3,2,1) but (1,2,3). Default stride is 1, open-ended +** ranges are not permitted. +** +** M. Fitzpatrick, NOAO, June 2007 (Translated from IRAF xtools$ranges.x) +** +******************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <dirent.h> +#include <unistd.h> +#include <ctype.h> +#include "VOClient.h" +#include "voAppsP.h" + + +#define FIRST 1 /* Default starting range */ +#define LAST MAX_INT /* Default ending range */ +#define STEP 1 /* Default step */ +#define EOLIST 0 /* End of list */ + +#define MAX_INT 65535 +#define INDEF 65534 +/*#define ERR -1*/ +#define EOS '\0' +#define OK 0 + + +static int ctoi (char *str, int *ip, int *ival); + +/************************************************************************* +** DECODERANGES -- Parse a string containing a list of integer numbers or +** ranges, delimited by either spaces or commas. Return as output a list +** of ranges defining a list of numbers, and the count of list numbers. +** Range limits must be positive nonnegative integers. ERR is returned as +** the function value if a conversion error occurs. The list of ranges is +** delimited by EOLIST. +*/ +int +vot_decodeRanges (range_string, ranges, max_ranges, nvalues) + +char *range_string; /* Range string to be decoded */ +int ranges[]; /* Range array */ +int max_ranges; /* Maximum number of ranges */ +int *nvalues; /* The number of values in the ranges */ + +{ + int ip, nrange, first, last, step, diff, *ra = &ranges[0]; + + ip = 0; + *nvalues = 0; + + for (nrange = 0; nrange < (max_ranges - 1); nrange += 3) { + /* Defaults to all nonnegative integers. + */ + first = FIRST; + last = LAST; + step = STEP; + + /* Skip delimiters. + */ + while (isspace(range_string[ip]) || range_string[ip] == ',') + ip++; + + /* Get first limit. Must be a number, '-', 'x', or EOS. + ** If not return ERR. + */ + if (range_string[ip] == EOS) { /* end of list */ + if (nrange == 0) { + ra[0] = first; /* null string defaults */ + ra[1] = last; + ra[2] = step; + ra[3] = EOLIST; + *nvalues = MAX_INT; + return (OK); + } else { + ra[nrange] = EOLIST; + return (OK); + } + } else if (range_string[ip] == '-') + ; + else if (range_string[ip] == 'x') + ; + else if (isdigit((int)range_string[ip])) { /* ,n.. */ + if (ctoi (range_string, &ip, &first) == 0) + return (ERR); + } else + return (ERR); + + /* Skip delimiters. + */ + while (isspace(range_string[ip]) || range_string[ip] == ',') + ip++; + + /* Get last limit. Must be '-', or 'x' otherwise last = first. + */ + if (range_string[ip] == 'x') + ; + else if (range_string[ip] == '-') { + ip++; + while (isspace(range_string[ip]) || range_string[ip] == ',') + ip++; + if (range_string[ip] == EOS) + ; + else if (isdigit((int)range_string[ip])) { + if (ctoi (range_string, &ip, &last) == 0) + return (ERR); + } else if (range_string[ip] == 'x') + ; + else + return (ERR); + } else + last = first; + + /* Skip delimiters + */ + while (isspace(range_string[ip]) || range_string[ip] == ',') + ip++; + + /* Get step. Must be 'x' or assume default step. + */ + if (range_string[ip] == 'x') { + ip++; + while (isspace(range_string[ip]) || range_string[ip] == ',') + ip++; + if (range_string[ip] == EOS) + ; + else if (isdigit((int)range_string[ip])) { + if (ctoi (range_string, &ip, &step) == 0) + ; + if (step == 0) + return (ERR); + } else if (range_string[ip] == '-') + ; + else + return (ERR); + } + + /* Output the range triple. + */ + ra[nrange ] = first; + ra[nrange+1] = last; + ra[nrange+2] = step; + diff = last - first; + if (diff < 0) + diff = - (diff); + *nvalues = *nvalues + diff / step + 1; + } + + return (ERR); /* ran out of space */ +} + + +/* GET_NEXT_NUMBER -- Given a list of ranges and the current file number, +** find and return the next file number. Selection is done in such a way +** that list numbers are always returned in monotonically increasing order, +** regardless of the order in which the ranges are given. Duplicate entries +** are ignored. EOF is returned at the end of the list. +*/ +int +get_next_number (int ranges[], int number) +{ + int a, b, ip, first, last, step, next_number, remainder; + + + /* If number+1 is anywhere in the list, that is the next number, + ** otherwise the next number is the smallest number in the list which + ** is greater than number+1. + */ + number = number + 1; + next_number = MAX_INT; + + for (ip=0; ranges[ip] != EOLIST; ip=ip+3) { + a = ranges[ip]; + b = ranges[ip + 1]; + first = (a < b) ? a : b; + last = (a > b) ? a : b; + step = ranges[ip+2]; + if (step == 0) { + fprintf (stderr, "ERROR: Step size of zero in range list"); + return (0); + } + + if (number >= first && number <= last) { + remainder = (number - first) % step; + if (remainder == 0) + return (number); + if ((number - remainder + step) <= last) + next_number = number - remainder + step; + } else if (first > number) + next_number = (next_number < first) ? next_number : first; + } + + if (next_number == MAX_INT) + return (EOF); + else { + number = next_number; + return (number); + } +} + + +/* IS_IN_RANGE -- Test number to see if it is in range. +*/ +int +is_in_range (int ranges[], int number) +{ + int a, b, ip, first, last, step, num = number; + + for (ip=0; ranges[ip] != EOLIST; ip += 3) { + a = ranges[ip]; + b = ranges[ip + 1]; + first = (a < b) ? a : b; + last = (a > b) ? a : b; + step = ranges[ip+2]; + if (num >= first && num <= last) + if (((num - first) % step) == 0) + return (1); + } + + return (0); +} + + +/* CTOI -- Simple character to integer (decimal radix) that advances the +** character pointer (index). +*/ +static int +ctoi (char *str, int *ip, int *ival) +{ + int neg, sum, ip_start; + + while (isspace (str[*ip])) + *ip = *ip + 1; + ip_start = *ip; + + if ((neg = (str[*ip] == '-'))) + *ip = *ip + 1; + + sum = 0; + while (isdigit ((int) str[*ip])) { + sum = sum * 10 + (int) (str[*ip] - '0'); + *ip = *ip + 1; + } + + if (neg) + *ival = -sum; + else + *ival = sum; + + return (*ip - ip_start); +} diff --git a/vendor/voclient/voapps/lib/voSCS.c b/vendor/voclient/voapps/lib/voSCS.c new file mode 100644 index 00000000..d248489e --- /dev/null +++ b/vendor/voclient/voapps/lib/voSCS.c @@ -0,0 +1,265 @@ +/************************************************************************ +** VOSCS.C -- Worker procedure to query a Simple Cone Search service. +** +** M. Fitzpatrick, NOAO, July 2007 +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include "VOClient.h" +#include "voAppsP.h" +#include "samp.h" + + +extern int errno; +extern int debug, verbose, all_named, all_data, save_res, extract, quiet; +extern int meta, dverbose, count, count_only, file_get, use_name, format; +extern int id_col, samp, samp_p; + +extern char *output; + +int vot_callConeSvc (svcParams *pars); + +extern int vot_extractResults (char *result, char delim, svcParams *pars); +extern int vot_printCount (Query query, svcParams *pars, int *count); +extern int vot_countResults (char *result); +extern char vot_svcTypeCode (int type); +extern void vot_printCountHdr (void); +extern void vot_printCountLine (int nrec, svcParams *pars); +extern void vot_dalExit (int code, int count); +extern void vot_printHdr (int fd, svcParams *pars); + +extern void vot_printAttrs (char *fname, Query query, char *id); +extern char *vot_normalize (char *str); +extern char *vot_getOFName (svcParams *pars, char *extn, int pid); +extern char *vot_getOFIndex (svcParams *pars, char *extn, int pid); + + +/************************************************************************ +** VOT_CALLCONESVC -- Call a Cone Search service. +*/ +int +vot_callConeSvc (svcParams *pars) +{ + char *result = (char *)NULL; + char *extn, fname[SZ_LINE], delim; + DAL cone; /* DAL Connection handle */ + Query query; /* Query handle */ + pid_t cpid; + int fd, res_count=0, code; + + + if (debug) + fprintf (stderr, "coneCaller(%s:%d): ra = %f dec = %f\n", + pars->name, getpid(), pars->ra, pars->dec); + + + if ((cpid = fork()) < 0) { + fprintf (stderr, + "vot_callConeSvc: Unable to create child process, exiting\n"); + vot_dalExit (-1, 0); + + } else if (cpid > 0) { /* Parent process */ + return (cpid); + + } else { /* Child process */ + + if (getenv ("VOC_NO_NETWORK")) + return (OK); + + /* Initialize the VOClient code. Error messages are printed by the + ** interface so we just quit if there is a problem. + */ + if (voc_initVOClient ((char *) NULL) == ERR) + vot_dalExit (E_VOCINIT, 0); + + /* Get a new connection to the named service and form the query. + if (all_data || verbose > 1) + */ + cone = voc_openConeConnection (pars->service_url); + query = voc_getConeQuery (cone, pars->ra, pars->dec, + (meta ? 0.0 : pars->sr)); + if (verbose > 1) + (void) voc_addIntParam (query, "VERB", (all_data ? 3 : verbose)); + + + /* Execute the query. + */ + if (debug) { + fprintf (stderr, "coneCaller(%s:%d): executing query....\n", + pars->name, getpid()); + fprintf (stderr, "Executing Cone Query:\n %s\n\n", + voc_getQueryString (query, CONE_CONN, 0)); + } + + if (count_only) { +/* + if ((code = vot_printCount (query, pars, &res_count)) != E_NONE) { + vot_dalExit (code, res_count); + } +*/ + code = vot_printCount (query, pars, &res_count); + vot_dalExit (code, res_count); + + } else if (meta) { + bzero (fname, SZ_FNAME); + if (output) + strcpy (fname, output); + else + sprintf (fname, "%s_%c.meta", vot_normalize (pars->name), + vot_svcTypeCode(pars->type)); + vot_printAttrs (fname, query, pars->identifier); + + } else { + + switch (pars->fmt) { + case F_ASCII: + extn = "asv", delim = ' '; + result = voc_executeASCII (query); + break; + case F_RAW: + extn = "xml", delim = '\0'; + result = voc_executeVOTable (query); + break; + case F_RAW | F_XML: + extract |= EX_XML; + extn = "xml"; delim = '\0'; + result = voc_executeVOTable (query); + break; + case F_CSV: + extn = "csv", delim = ','; + result = voc_executeCSV (query); + break; + case F_CSV | F_HTML: + extract |= EX_HTML; + extn = "csv", delim = ','; + result = voc_executeCSV (query); + break; + case F_CSV | F_KML: + extract |= EX_KML; + extn = "csv", delim = ','; + result = voc_executeCSV (query); + break; + case F_TSV: + extn = "tsv", delim = '\t'; + result = voc_executeTSV (query); + break; + default: + fprintf (stderr, "coneCaller: Unknown format: %d\n", pars->fmt); + vot_dalExit (-1, 0); + } + + if (!result) + vot_dalExit (E_NODATA, 0); + else if (pars->fmt != F_RAW) + res_count = vot_extractResults (result, delim, pars); + else + res_count = vot_countResults (result); + + if (count && (!output || (output && output[0] != '-'))) + vot_printCountLine (res_count, pars); +#ifdef EARLY_EXIT + if (res_count == 0) { + voc_closeConnection (siap); + voc_closeVOClient (0); + if (result) free ((char *) result); + vot_dalExit (E_NODATA, res_count); + } +#endif + + + /* Check for a NULL result indicating an error in the call. + */ + if (result == (char *)NULL) { + char *err; + extern char *voc_getErrMsg(); + + if (strncmp ((err = voc_getErrMsg()), "ERROR", 5) == 0) { + if (verbose > 1) + fprintf (stderr, "Pid %d: %s\n", getpid(), err); + vot_dalExit (E_REQFAIL, res_count); + + } else + vot_dalExit (E_NODATA, res_count); + } + + if (all_data && pars->type == SVC_VIZIER) { + char *vot_urlFname (char *url); + + if (output) { + /* + */ + if (output[0] == '-') + strcpy (fname, vot_getOFName(pars,extn,(int)getpid())); + else + sprintf (fname, "%s_%s.%s", + output, vot_urlFname(pars->service_url), extn); + + } else + sprintf (fname, "%s%s.%s", + vot_normalize(pars->name), + vot_urlFname(pars->service_url), extn); + + } else if (use_name || all_named || id_col) { + strcpy (fname, vot_getOFName (pars, extn, (int)getpid())); + + } else { + strcpy (fname, vot_getOFIndex (pars, extn, (int)getpid())); + } + + if (output && output[0] == '-' && (! extract & EX_COLLECT)) { + write (fileno(stdout), result, strlen (result)-1); + + } else if (format != (F_CSV|F_HTML) && format != (F_CSV|F_KML)) { + + if ((fd = open (fname, O_WRONLY|O_CREAT, 0644)) < 0){ + fprintf (stderr, "Error opening file '%s'\n", fname); + vot_dalExit (E_FILOPEN, res_count); + } + + /* Output the result. + if (pars->fmt = F_CSV || pars->fmt == F_TSV) + vot_printHdr (fd, pars); + */ + write (fd, result, strlen (result)-1); + close (fd); + } + } + + voc_closeConnection (cone); /* close the cone connection */ + voc_closeVOClient (0); /* close VOClient connection */ + + if (result) free ((void *) result); /* free local storage */ + + if (debug) + fprintf (stderr, "coneCaller(%s:%d): exiting....\n", + pars->name, getpid()); + + if (samp) { + char url[SZ_FNAME], cwd[SZ_FNAME]; + extern int samp_tableLoadVOTable (); + + samp_p = sampInit ("VOData", "VOClient Data Access"); + samp_setSyncMode (samp_p); + sampStartup (samp_p); + + memset (cwd, 0, SZ_FNAME); + if (getcwd (cwd, SZ_FNAME) < 0) + strcpy (cwd, "./"); + + memset (url, 0, SZ_FNAME); + sprintf (url, "file://%s/%s", cwd, fname); + (void) samp_tableLoadVOTable (samp_p, "all", url, NULL, NULL); + + samp_UnRegister (samp_p); + } + + if (res_count == 0) + unlink (fname); + vot_dalExit (0, res_count); + } + + return (OK); +} diff --git a/vendor/voclient/voapps/lib/voSIAP.c b/vendor/voclient/voapps/lib/voSIAP.c new file mode 100644 index 00000000..74506183 --- /dev/null +++ b/vendor/voclient/voapps/lib/voSIAP.c @@ -0,0 +1,295 @@ +/************************************************************************ +** VOSIAP.C -- Worker procedure to make a query to an SIAP service. +** +** M. Fitzpatrick, NOAO, July 2007 +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include "VOClient.h" +#include "voAppsP.h" +#include "samp.h" + + +extern int errno; +extern int debug, verbose, all_named, all_data, save_res, extract, quiet; +extern int meta, dverbose, count, count_only, file_get, use_name, format; +extern int id_col, samp, samp_p; + +extern char *output; + + +int vot_callSiapSvc (svcParams *pars); +char *vot_validateFile (char *fname); + +extern int vot_extractResults (char *result, char delim, svcParams *pars); +extern int vot_printCount (Query query, svcParams *pars, int *count); +extern int vot_countResults (char *result); +extern void vot_printCountHdr (void); +extern void vot_printCountLine (int nrec, svcParams *pars); +extern void vot_dalExit (int code, int count); +extern void vot_printHdr (int fd, svcParams *pars); +extern void vot_printAttrs (char *fname, Query query, char *id); +extern char vot_svcTypeCode (int type); +extern char *vot_normalize (char *str); +extern char *vot_getOFName (svcParams *pars, char *extn, int pid); +extern char *vot_getOFIndex (svcParams *pars, char *extn, int pid); + + + +/************************************************************************ +** VOT_CALLSIAPSVC -- Call a Simple Image Access service. +*/ +int +vot_callSiapSvc (svcParams *pars) +{ + char *result = (char *)NULL; + char *extn, fname[SZ_LINE]; + DAL siap; /* DAL Connection handle */ + Query query; /* Query handle */ + pid_t cpid; + int fd, code, res_count = 0; + + + + if (debug) + fprintf (stderr, "siapCaller(%s:%d): ra = %f dec = %f\n", + pars->name, getpid(), pars->ra, pars->dec); + + + if ((cpid = fork()) < 0) { + fprintf (stderr, + "vot_callSiapSvc: Unable to create child process, exiting\n"); + exit (-1); + + } else if (cpid > 0) { /* Parent process */ + return (cpid); + + } else { /* Child process */ + + if (getenv("VOC_NO_NETWORK")) + return (OK); + + /* Initialize the VOClient code. Error messages are printed by the + ** interface so we just quit if there is a problem. + */ + if (voc_initVOClient ((char *) NULL) == ERR) + vot_dalExit (E_VOCINIT, 0); + + /* Get a new connection to the named service and form the query. + */ + siap = voc_openSiapConnection (pars->service_url); + + if (meta) + query = voc_getSiapQuery (siap, 0.0, 0.0, 0.0, 0.0, "METADATA"); + else + query = voc_getSiapQuery (siap, pars->ra, pars->dec, + pars->sr, pars->sr, (char *)NULL); + + /* Not all SIAP services support VERB, leave it out for now.... + */ + if (verbose > 1) + (void) voc_addIntParam (query, "VERB", (all_data ? 3 : verbose)); + + + /* Execute the query. + */ + if (debug) { + fprintf (stderr, "siapCaller(%s:%d): executing query....%d\n", + pars->name, getpid(), pars->fmt); + fprintf (stderr, "Executing SIAP Query(%d):\n %s\n\n", query, + voc_getQueryString (query, SIAP_CONN, 0)); + } + + + if (count_only) { + if ((code = vot_printCount (query, pars, &res_count)) != E_NONE) { + vot_dalExit (code, res_count); + } + + } else if (meta) { + memset (fname, 0, SZ_LINE); + if (output) + strcpy (fname, output); + else + sprintf (fname, "%s_%c.meta", vot_normalize (pars->name), + vot_svcTypeCode(pars->type)); + vot_printAttrs (fname, query, pars->identifier); + + } else { + char delim; + + switch (pars->fmt) { + case F_ASCII: + extn = "asv"; delim = ' '; + result = voc_executeASCII (query); + break; + case F_RAW: + extn = "xml"; delim = '\0'; + result = voc_executeVOTable (query); + break; + case F_RAW | F_XML: + extract |= EX_XML; + extn = "xml"; delim = '\0'; + result = voc_executeVOTable (query); + break; + case F_CSV: + extn = "csv"; delim = ','; + result = voc_executeCSV (query); + break; + case F_CSV | F_HTML: + extract |= EX_HTML; + extn = "csv"; delim = ','; + result = voc_executeCSV (query); + break; + case F_CSV | F_KML: + extract |= EX_KML; + extn = "csv"; delim = ','; + result = voc_executeCSV (query); + break; + case F_TSV: + extn = "tsv"; delim = '\t'; + result = voc_executeTSV (query); + break; + default: + fprintf (stderr, "siapCaller: Unknown format: %d\n", pars->fmt); + exit (-1); + } + + if (!result) { + vot_dalExit (E_NODATA, 0); + } else if (pars->fmt != F_RAW) { + res_count = vot_extractResults (result, delim, pars); + } else if (pars->fmt == F_RAW) { + res_count = vot_countResults (result); + } + + if (count && (!output || (output && output[0] != '-'))) + vot_printCountLine (res_count, pars); +#ifdef EARLY_EXIT + if (res_count == 0) { + voc_closeConnection (siap); + voc_closeVOClient (0); + if (result) free ((char *) result); + vot_dalExit (E_NODATA, res_count); + } +#endif + + /* Check for a NULL result indicating an error in the call. + */ + if (result == (char *)NULL) { + char *err; + extern char *voc_getErrMsg(); + + err = voc_getErrMsg (); + if (err && strncmp (err, "ERROR", 5) == 0) { + if (verbose > 1) + fprintf (stderr, "Pid %d: %s\n", getpid(), err); + vot_dalExit (E_REQFAIL, res_count); + } else + vot_dalExit (E_NODATA, res_count); + } + + if (use_name || all_named || id_col) + strcpy (fname, vot_getOFName (pars, extn, (int)getpid())); + else + strcpy (fname, vot_getOFIndex (pars, extn, (int)getpid())); + + + if (output && output[0] == '-' && (! extract & EX_COLLECT)) { + write (fileno(stdout), result, strlen (result)-1); + + } else if (format != (F_CSV|F_HTML) && format != (F_CSV|F_KML)) { + if ((fd = open (fname, O_WRONLY|O_CREAT, 0644)) < 0){ + fprintf (stderr, "Error opening file '%s'\n", fname); + vot_dalExit (E_FILOPEN, res_count); + } + + /* Output the result. + if (pars->fmt = F_CSV || pars->fmt == F_TSV) + vot_printHdr (fd, pars); + */ + if (result) + write (fd, result, strlen (result)-1); + close (fd); + + } + } + + voc_closeConnection (siap); /* close the siap connection */ + voc_closeVOClient (0); /* close VOClient connection */ + + if (result) free ((void *) result); /* free local storage */ + + if (debug) { + fprintf (stderr, "siapCaller(%s:%d): exiting....\n", + pars->name, getpid()); + } + + if (samp) { + char url[SZ_FNAME], cwd[SZ_FNAME]; + extern int samp_tableLoadVOTable (); + + samp_p = sampInit ("VOData", "VOClient Data Access"); + samp_setSyncMode (samp_p); + sampStartup (samp_p); + + memset (cwd, 0, SZ_FNAME); + if (getcwd (cwd, SZ_FNAME) < 0) + strcpy (cwd, "./"); + + memset (url, 0, SZ_FNAME); + sprintf (url, "file://%s/%s", cwd, fname); + (void) samp_tableLoadVOTable (samp_p, "all", url, NULL, NULL); + + samp_UnRegister (samp_p); + } + + if (res_count == 0) + unlink (fname); + vot_dalExit (E_NONE, res_count); /* no error */ + } + + return (OK); +} + + +/************************************************************************ +** +*/ +char * +vot_validateFile (char *fname) +{ + int fd, size; + static char buf[10], new[SZ_FNAME], *extn; + + + if ((fd = open (fname, O_RDONLY, 0777)) <= 0) { + unlink (fname); + return (0); + } + + if ((size = read (fd, buf, 10))) + close (fd); + + if (strncmp ("SIMPLE", buf, 6) == 0) { + extn = "fits"; + } else if (strncmp ("GIF8", buf, 4) == 0) { + extn = "gif"; + } else if (strncmp ("PNG\r\n", &buf[1], 5) == 0) { + extn = "png"; + } else if (buf[0] == '\377' && buf[1] == '\330' && buf[2] == '\377' && + buf[3] == '\340') { + extn = "jpg"; + } else if (buf[0] == '\037' && buf[1] == '\213') { + extn = "gz"; + } else + return (fname); + + sprintf (new, "%s.%s", fname, extn); + rename (fname, new); + + return (new); +} diff --git a/vendor/voclient/voapps/lib/voSSAP.c b/vendor/voclient/voapps/lib/voSSAP.c new file mode 100644 index 00000000..fa86d139 --- /dev/null +++ b/vendor/voclient/voapps/lib/voSSAP.c @@ -0,0 +1,233 @@ +/************************************************************************ +** VOSSAP.C -- Worker procedure to make a query to an SSAP service. +** +** M. Fitzpatrick, NOAO, Februaary 2009 +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include "VOClient.h" +#include "voAppsP.h" + + +extern int errno; +extern int debug, verbose, all_named, all_data, save_res, extract, quiet; +extern int meta, dverbose, count, count_only, file_get, use_name, format; +extern int id_col; + +extern char *output, *d2_band, *d2_time, *d2_format, *d2_version; + + +int vot_callSsapSvc (svcParams *pars); + +extern int vot_extractResults (char *result, char delim, svcParams *pars); +extern int vot_printCount (Query query, svcParams *pars, int *count); +extern int vot_countResults (char *result); +extern char vot_svcTypeCode (int type); +extern char *vot_normalize (char *str); +extern char *vot_getOFName (svcParams *pars, char *extn, int pid); +extern char *vot_getOFIndex (svcParams *pars, char *extn, int pid); +extern void vot_printCountHdr (void); +extern void vot_printCountLine (int nrec, svcParams *pars); +extern void vot_dalExit (int code, int count); +extern void vot_printHdr (int fd, svcParams *pars); +extern void vot_printAttrs (char *fname, Query query, char *id); + + + +/************************************************************************ +** VOT_CALLSSAPSVC -- Call a Simple Image Access service. +*/ +int +vot_callSsapSvc (svcParams *pars) +{ + char *result = (char *)NULL; + char *extn, fname[SZ_LINE]; + DAL ssap; /* DAL Connection handle */ + Query query; /* Query handle */ + pid_t cpid; + int fd, code, res_count = 0; + + + + if (debug) + fprintf (stderr, "ssapCaller(%s:%d): ra = %f dec = %f\n", + pars->name, getpid(), pars->ra, pars->dec); + + + if ((cpid = fork()) < 0) { + fprintf (stderr, + "vot_callSsapSvc: Unable to create child process, exiting\n"); + exit (-1); + + } else if (cpid > 0) { /* Parent process */ + return (cpid); + + } else { /* Child process */ + + if (getenv("VOC_NO_NETWORK")) + return (OK); + + /* Initialize the VOClient code. Error messages are printed by the + ** interface so we just quit if there is a problem. + */ + if (voc_initVOClient ((char *) NULL) == ERR) + vot_dalExit (E_VOCINIT, 0); + + /* Get a new connection to the named service and form the query. + */ + ssap = voc_openSsapConnection (pars->service_url); + if (meta) { + query = voc_getSsapQuery (ssap, 0.0, 0.0, 0.0, + (char *) NULL, (char *) NULL, "METADATA"); + } else { + query = voc_getSsapQuery (ssap, pars->ra, pars->dec, pars->sr, + (char *) d2_band, /* BAND */ + (char *) d2_time, /* TIME */ + (char *) d2_format); /* FORMAT */ + + if (d2_version) + (void) voc_addStringParam (query, "VERSION", d2_version); + (void) voc_addStringParam (query, "REQUEST", "queryData"); + } + + + /* Execute the query. + */ + if (debug) { + fprintf (stderr, "ssapCaller(%s:%d): executing query....%d\n", + pars->name, getpid(), pars->fmt); + fprintf (stderr, "Executing SSAP Query(%d):\n %s\n\n", query, + voc_getQueryString (query, SSAP_CONN, 0)); + } + + + if (count_only) { + if ((code = vot_printCount (query, pars, &res_count)) != E_NONE) { + vot_dalExit (code, res_count); + } + + } else if (meta) { + bzero (fname, SZ_FNAME); + if (output) + strcpy (fname, output); + else + sprintf (fname, "%s_%c.meta", vot_normalize (pars->name), + vot_svcTypeCode(pars->type)); + vot_printAttrs (fname, query, pars->identifier); + + } else { + char delim; + + switch (pars->fmt) { + case F_ASCII: + extn = "asv"; delim = ' '; + result = voc_executeASCII (query); + break; + case F_RAW: + extn = "xml"; delim = '\0'; + result = voc_executeVOTable (query); + break; + case F_RAW | F_XML: + extract |= EX_XML; + extn = "xml"; delim = '\0'; + result = voc_executeVOTable (query); + break; + case F_CSV: + extn = "csv"; delim = ','; + result = voc_executeCSV (query); + break; + case F_CSV | F_HTML: + extract |= EX_HTML; + extn = "csv"; delim = ','; + result = voc_executeCSV (query); + break; + case F_CSV | F_KML: + extract |= EX_KML; + extn = "csv"; delim = ','; + result = voc_executeCSV (query); + break; + case F_TSV: + extn = "tsv"; delim = '\t'; + result = voc_executeTSV (query); + break; + default: + fprintf (stderr, "ssapCaller: Unknown format: %d\n", pars->fmt); + exit (-1); + } + + if (!result) + vot_dalExit (E_NODATA, 0); + else if (pars->fmt != F_RAW) + res_count = vot_extractResults (result, delim, pars); + else if (pars->fmt == F_RAW) + res_count = vot_countResults (result); + + if (count && (!output || (output && output[0] != '-'))) + vot_printCountLine (res_count, pars); +#ifdef EARLY_EXIT + if (res_count == 0) { + voc_closeConnection (siap); + voc_closeVOClient (0); + if (result) free ((char *) result); + vot_dalExit (E_NODATA, res_count); + } +#endif + + + /* Check for a NULL result indicating an error in the call. + */ + if (result == (char *)NULL) { + char *err; + extern char *voc_getErrMsg(); + if (strncmp ((err = voc_getErrMsg()), "ERROR", 5) == 0) { + if (verbose > 1) + fprintf (stderr, "Pid %d: %s\n", getpid(), err); + vot_dalExit (E_REQFAIL, res_count); + } else + vot_dalExit (E_NODATA, res_count); + } + + if (use_name || all_named || id_col) + strcpy (fname, vot_getOFName (pars, extn, (int)getpid())); + else + strcpy (fname, vot_getOFIndex (pars, extn, (int)getpid())); + + + if (output && output[0] == '-' && (! extract & EX_COLLECT)) { + write (fileno(stdout), result, strlen (result)-1); + + } else if (format != (F_CSV|F_HTML) && format != (F_CSV|F_KML)) { + if ((fd = open (fname, O_WRONLY|O_CREAT, 0644)) < 0){ + fprintf (stderr, "Error opening file '%s'\n", fname); + vot_dalExit (E_FILOPEN, res_count); + } + + /* Output the result. + if (pars->fmt = F_CSV || pars->fmt == F_TSV) + vot_printHdr (fd, pars); + */ + if (result) + write (fd, result, strlen (result)-1); + close (fd); + + } + } + + voc_closeConnection (ssap); /* close the ssap connection */ + voc_closeVOClient (0); /* close VOClient connection */ + + if (result) free ((void *) result); /* free local storage */ + + if (debug) { + fprintf (stderr, "ssapCaller(%s:%d): exiting....\n", + pars->name, getpid()); + } + + vot_dalExit (E_NONE, res_count); /* no error */ + } + + return (OK); +} diff --git a/vendor/voclient/voapps/lib/voSvc.c b/vendor/voclient/voapps/lib/voSvc.c new file mode 100644 index 00000000..b0b56265 --- /dev/null +++ b/vendor/voclient/voapps/lib/voSvc.c @@ -0,0 +1,874 @@ +/**************************************************************************** +** VOARGS.C -- Procedures for commandline argument handling. We also do +** some of the heavy lifting for registry and object resolution. +** +** M. Fitzpatrick, NOAO, June 2007 +*/ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#include <unistd.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#include "VOClient.h" +#include "votParse.h" +#include "voAppsP.h" + + +#define SVC_DEBUG 0 + + +extern int nobjects, nservices, inventory; +extern int verbose, quiet, debug, errno, force_svc, meta; +extern int all_data, use_name, all_named, url_proc, svc_list; +extern int force_read, table_hskip, table_nlines, table_sample; +#ifdef REG10_KLUDGE +extern int reg10; +#endif +extern char *typestr, *bpass, *delim, *cols, *ecols, *output; + +extern Service *svcList, *svcTail; + +int svcIndex = 0; + + +int vot_parseServiceList (char *list, int dalOnly); +int vot_printServiceList (FILE *fd); +int vot_printServiceVOTable (FILE *fd); +int vot_isSupportedSvc (char *type); + +void vot_addToSvcList (char *name, char *ident,char *url, char *type, + char *title); +void vot_freeServiceList (void); +void vot_resetServiceCounters (void); +void vot_readSvcFile (char *fname, int dalOnly); + +static int vot_serviceResolver (char *idlist, int dalOnly); +static int isResourceVOTable (char *fname); +static int vot_loadResourceVOTable (char *fname); + +static void vot_regCacheResults (char *fname, char *results, int nres); + +static char *vot_regGetCacheResults (char *fname, int *nres); +static char *vot_regIsCached (char *id, char *type, char *bpass); +static char *vot_regCacheName (char *id, char *type, char *bpass); + +extern int vot_callConeSvc (svcParams *pars); +extern int vot_callSiapSvc (svcParams *pars); +extern int vot_callSsapSvc (svcParams *pars); +extern void vot_addToAclist (char *url, char *fname); +extern char *vot_urlFname (char *url); +extern char *vot_normalizeCoord (char *coord); +extern char *vot_normalize (char *str); + + + +/* Utility procedures. +*/ +extern char *strcasestr (); + + + + +/**************************************************************************** +** Parse a string containing service names. The string may be a single +** name, a comma-delimited list, or the name of a file containing the same. +*/ +int +vot_parseServiceList (char *list, int dalOnly) +{ + FILE *fd; + /*char name[SZ_FNAME];*/ + char *name; + + extern char *vot_getline (FILE *fd); + + + if (access (list, R_OK) == 0) { + + if (isResourceVOTable (list)) { + nservices += vot_loadResourceVOTable (list); + + } else { + + /* Process the file contents. + */ + if ((fd = fopen (list, "r")) == (FILE *) NULL) { + fprintf (stderr, "ERROR: Cannot open file '%s'\n", list); + return (1); + } + + while ((name = vot_getline (fd))) + vot_serviceResolver (name, dalOnly); + + fclose (fd); + } + + } else + vot_serviceResolver (list, dalOnly); + + if (debug) + vot_printServiceList (stderr); + if (svc_list) { + FILE *fd; + char listfile[SZ_FNAME]; + + memset (listfile, 0, SZ_FNAME); + sprintf (listfile, "%s.services", output); + if ((fd = fopen (listfile, "w+")) != (FILE *) NULL) { + vot_printServiceList (fd); + fclose (fd); + } + } + + return (0); +} + + +/**************************************************************************** +** LOADRESOURCEVOTABLE -- Read a Resource VOTable and load the Service list +** with its contents. +*/ +static int +vot_loadResourceVOTable (char *fname) +{ + int vot = 0, i; + int nr = 0, nc = 0, nresults = 0; + int c_url, c_name, c_id, c_type, c_title; + char url[SZ_LINE], name[SZ_FNAME], id[SZ_FNAME]; + char type[SZ_FNAME], title[SZ_LINE]; + + + if ((vot = vot_openVOTABLE (fname)) ) { + + int res, tab, data, tdata; + + res = vot_getRESOURCE (vot); /* get handles */ + if ((tab = vot_getTABLE (res)) <= 0) + return (0); + if ((data = vot_getDATA (tab)) <= 0) + return (0); + if ((tdata = vot_getTABLEDATA (data)) <= 0) + return (0); + nr = vot_getNRows (tdata); + nc = vot_getNCols (tdata); + + c_name = vot_colByName (tab, "shortName", ""); + c_url = vot_colByName (tab, "serviceURL", "accessURL"); + c_id = vot_colByName (tab, "identifier", ""); + c_type = vot_colByName (tab, "type", "capabilityclass"); + c_title = vot_colByName (tab, "title", ""); + + if (SVC_DEBUG) + fprintf (stderr, "name:%d url:%d id:%d type:%d title:%d\n", + c_name, c_url, c_id, c_type, c_title); + + for (i=0; i < nr; i++) { + bzero (name, SZ_FNAME); + strcpy (name, vot_getTableCell (tdata, i, c_name)); + + bzero (url, SZ_LINE); + strcpy (url, vot_getTableCell (tdata, i, c_url)); + + bzero (id, SZ_FNAME); + strcpy (id, vot_getTableCell (tdata, i, c_id)); + + bzero (type, SZ_FNAME); + strcpy (type, vot_getTableCell (tdata, i, c_type)); + + if (strcasestr ("SimpleImageAccess", type)) + strcpy (type, "SIAP"); + if (strcasestr ("ConeSearch", type)) + strcpy (type, "CONE"); + if (strcasestr ("skyservice", type)) + strcpy (type, "TABULARSKYSERVICE"); + + bzero (title, SZ_LINE); + strcpy (title, vot_getTableCell (tdata, i, c_title)); + + /* Skip services we don't yet support. + */ + if (! vot_isSupportedSvc (type) && !meta && !inventory) { + if (!quiet && verbose > 1) + fprintf (stderr, + "# Unsupported type %s for '%s', skipping...\n", type,name); + } else { + vot_addToSvcList (name, id, url, type, title); + nresults++; + } + } + } + + if (vot) + vot_closeVOTABLE (vot); + + return (nresults); +} + + +/**************************************************************************** +** ISRESOURCEVOTABLE -- Test a file or string to see if it's a Resource +** VOTable by looking for a <FIELD> element with a 'ShortName' attribute. +*/ +static int +isResourceVOTable (char *fname) +{ + int vot = 0, res, tab, field; + char name[SZ_FNAME], *attr = NULL; + extern int isVOTable (char *fname); + + + /* First, make sure that it's at least a VOTable. + */ + if (isVOTable (fname) == 0) + return (0); + + + /* Open it, looking for something we'd only expect from a + ** Resource VOTable like the 'ShortName' field. + */ + if ((vot = vot_openVOTABLE (fname)) ) { + res = vot_getRESOURCE (vot); + if ((tab = vot_getTABLE (res)) <= 0) + return (0); + + for (field=vot_getFIELD(tab); field; field=vot_getNext(field)) { + bzero (name, SZ_FNAME); + if ((attr = vot_getAttr (field, "name"))) + strcpy (name, attr); + + if (name[0] && strcasecmp (name, "ShortName") == 0) { + vot_closeVOTABLE (vot); + return (1); + } + } + } + + if (vot > 0) + vot_closeVOTABLE (vot); + + return (0); +} + + + +/**************************************************************************** +** Free the service list and reset the counter. +*/ +void +vot_freeServiceList () +{ + Service *cur, *next; + + for (cur=svcList; cur; cur=next) { + next = cur->next; + if (cur) + free ((void *) cur); + } + nservices = 0; + svcList = svcTail = (Service *) NULL; +} + + +/**************************************************************************** +** Reset the service counters. +*/ +void +vot_resetServiceCounters () +{ + Service *svc; + + for (svc=svcList; svc; svc=svc->next) + svc->count = svc->nfailed = svc->nnodata = 0; +} + + +/**************************************************************************** +** Resolve a service name/list to the proper service URL and store the +** result in the 'svcList' global which we assume is declared in the caller. +*/ +static int +vot_serviceResolver (char *idlist, int dalOnly) +{ + char *ip, *rp, *np, *id; + char sname[SZ_LINE], ident[SZ_LINE], title[SZ_LINE]; + char name[SZ_LINE], url[SZ_URL], type[SZ_LINE], *result; + int i, len, use_any = 0, nres=0, vot_regResolver (); + + extern int svcNumber; + + + /* Resolve the (list) of service names and add them to the + ** service list to be processed. + */ + ip = idlist; + + while (*ip) { + + /* Break up the input list into a single ID to resolve. + */ + id = ip; + while (*ip) { + if (*ip == ',' || *ip == '\n') { + *ip++ = '\0'; + break; + } else + ip++; + } + + if (access (id, R_OK) == 0) { /* file */ + vot_parseServiceList (id, dalOnly); + continue; + } else { /* service name */ + + if (url_proc && strncmp (id, "http", 4) == 0) { + /* A URL. This may be a user-defined service URL if the + ** the -s flag was given, otherwise we assume it's an + ** access reference we want to download. + */ + if (force_svc) { + sprintf (result, "%s\tUserSvc%d\tivo://user\t%s\n", + id, nres++, typestr); + + } else { + /* Argument was a URL but we're not asked to treat it + ** as a service URL, so just add it to the access list + ** and move on. When given on the command-line this is + ** handled by the argument parsing, here we do it mostly + ** to process URLs given in a file. + */ + vot_addToAclist (id, NULL); + url_proc++; + break; + } + + } else { + /* Try to resolve the id to a service URL. This may be + ** a substring of a ShortName or Identifier field and in + ** some cases may resolve to more than one resource. For + ** 'all_data' mode we assume the id is a ShortName that may + ** resolve to multiple tables having unique IVORNs so we + ** require an exact match of the name and add expand the + ** service list with each resolved identifier. + */ + + char *c_name = vot_regIsCached (id, typestr, bpass); + + if (c_name) { + result = vot_regGetCacheResults (c_name, &nres); + nservices += nres; + if (strcasecmp ("any", id) == 0) { + if (inventory) + nservices = -1; + else if (all_data) + use_any = 1; + } + + } else { + char *fields = + "AccessURL,ShortName,Identifier,CapabilityStandardID,Title"; + + if (strcasecmp ("any", id) == 0) { + if (typestr) { + use_any = 1; + nres = vot_regResolver ("%", typestr, bpass, "", + NULL, fields, -1, all_data, dalOnly, &result); + nservices += nres; + } else if (inventory) { + nservices = -1; + } else { + fprintf (stderr, + "Must specify service type for 'any' query\n"); + break; + } + } else { + /* If we're supporting Registry 1.0 then we need to + ** transform the VizieR ivorns before doing to search. + */ + if (strncasecmp("ivo://CDS.VizieR",id,16) == 0) + all_data++; +#ifdef REG10_KLUDGE + if (reg10 || + strncasecmp("ivo://CDS.VizieR",id,16) == 0) { + char ivorn[SZ_LINE]; + + bzero (ivorn, SZ_LINE); + strcpy (ivorn, id); + strcat (ivorn, "%"); + ivorn[9] = '/'; + all_data++; + nres = vot_regResolver (ivorn, typestr, bpass, "", + NULL, fields, -1, !all_data, dalOnly, &result); + + } else { +#endif + if (strncasecmp("ivo://CDS/VizieR",id,16) == 0) { + char ivorn[SZ_LINE]; + + bzero (ivorn, SZ_LINE); + strcpy (ivorn, id); + strcat (ivorn, "%"); + ivorn[9] = '.'; + nres = vot_regResolver (ivorn, typestr, bpass, + NULL, "", fields, -1, !all_data, 0, &result); + if (nres == 0) { + int len = strlen (ivorn); + char *ip = &ivorn[len-1]; + + for ( ; *ip != '/'; ip--) *ip = '\0'; + nres = vot_regResolver (ivorn, typestr, + bpass, "", NULL, fields, -1, !all_data, + 0, &result); + } + + } else { + nres = vot_regResolver (id, typestr, bpass, "", + NULL, fields, -1, !all_data, dalOnly, + &result); + if (nres == 0 && !all_data) { + /* No results for exact match, try again by + ** being a little more liberal with matching + */ + all_data++; + nres = vot_regResolver (id, typestr, bpass, + NULL, "", fields, -1, 0, dalOnly, + &result); + } + } +#ifdef REG10_KLUDGE + } +#endif + if (nres == 0) { + /* For no results from the registry, assume + ** any 'http' URI is instead a file to download. + */ + if (!url_proc && strncmp (id, "http", 4) == 0) { + vot_addToAclist (id, NULL); + url_proc++; + break; + } + } + nservices += nres; + } + if ((nres > 1 && verbose) && !all_data && !use_any) { + fprintf (stderr, + "# Service query '%s' non-unique (%d found)...\n", + id, nres); + } + + /* Cache the result. + */ + c_name = vot_regCacheName (id, typestr, bpass); + vot_regCacheResults (c_name, result, nres); + } + } + } + + /* Replace problem characters in the name so it can be used in + ** a filename. + */ + for (np=id; *np; np++) + if (*np == ' ' || *np == '/' || *np == '(' || *np == ')') + *np = '_'; + + + /* Loop over each of the resources found, parsing the result string + ** and adding each service in turn. If we're not doing all the data, + ** use the first result found and break. + */ + rp = &result[0]; + for (i=0; i < nres; i++) { + + /* Split the resolved string to the url and type. + */ + memset (url, 0, SZ_URL); + memset (sname, 0, SZ_LINE); + memset (ident, 0, SZ_LINE); + memset (type, 0, SZ_LINE); + memset (title, 0, SZ_LINE); + + for (np=url, len=SZ_URL; *rp && *rp != '\t' && len; len--) + *np++ = *rp++; + rp++; + for (np=sname, len=SZ_LINE; *rp && *rp != '\t' && len; len--) + *np++ = *rp++; + rp++; + for (np=ident, len=SZ_LINE; *rp && *rp != '\t' && len; len--) + *np++ = *rp++; + rp++; + for (np=type, len=SZ_LINE; *rp && *rp != '\t' && len; len--) + *np++ = *rp++; + rp++; + for (np=title, len=SZ_LINE; *rp && *rp != '\n' && len; len--) + *np++ = *rp++; + rp++; + + /* Skip services we don't yet support. + if (! vot_isSupportedSvc (type) && !meta) { + */ + if (! vot_isSupportedSvc (type)) { + if (!quiet && verbose > 1) + fprintf (stderr, + "# Unsupported service type '%s' for '%s', skipping...\n", + type, sname); + continue; + } + + /* Check for a specifically requested service number. + */ + if (svcNumber > 0) { + char *ip, *op, num[SZ_FNAME]; + + bzero (num, SZ_FNAME); + for (ip=sname; *ip && ! isdigit(*ip); ip++) ; + for (op=num; *ip && isdigit(*ip); ip++) + *op++ = *ip; + + if (atoi(num) != svcNumber) + continue; + } + + if (verbose && !quiet && !use_any && nres > 1) { + if (all_data) + fprintf (stderr, "# Using %s Resource %s_%s -> %s\n", + type, id, vot_urlFname(url), ident); + else + fprintf (stderr, "# Using %s Resource %s -> %s\n", + type, sname, ident); + if (debug) { + fprintf (stderr, "%d url = '%s'\n", i, url); + fprintf (stderr, "%d type = '%s'\n", i, type); + } + } + + /* Save results in the service list. + */ + bzero (name, SZ_LINE); + strcpy (name, (use_any || all_data ? sname : id)); + + vot_addToSvcList (name, ident, url, type, title); + + if (!all_data && !use_any) + break; + } + + if (result) + free ((char *)result); + } + + return (0); +} + + +/**************************************************************************** +** Utility routine to add a URL to the service list. +*/ +void +vot_addToSvcList (char *name, char *ident, char *url, char *type, char *title) +{ + Service *svc; + char *ip, *op; + + + if (url == (char *)NULL || strcasecmp ("NOT PROVIDED", url) == 0) { + fprintf (stderr, + "Warning: Empty ServiceURL for '%s', skipping...\n", name); + return; + } + + /* Save results in the service list. + */ + svc = (Service *)calloc (1,sizeof(Service)); + if (!svcList) + svcList = svcTail = svc; + else + svcTail->next = (Service *)svc; + + + /* Clean up any '&' encodings in the URL. + */ + for (ip = op = url; *ip; ) { + if (*ip == '&' && strncmp (ip, "&", 4) == 0) { + ip += ((strncmp (ip, "&", 5) == 0) ? 5 : 4); + *op++ = '&'; + } else + *op++ = *ip++; + } + *op = '\0'; + + + strcpy (svc->name, name); + strcpy (svc->service_url, url); + strcpy (svc->identifier, ident); + strcpy (svc->title, title); + if (strncasecmp (type, "cone", 4) == 0 || + strncasecmp (type, "catalog", 7) == 0) { + svc->func = &vot_callConeSvc; + if (strstr (url, "vizier")) { + svc->type = SVC_VIZIER; + } else + svc->type = SVC_CONE; + } else if (strncasecmp (type, "sia", 3) == 0 || + strncasecmp (type, "simpleimage", 9) == 0) { + svc->func = &vot_callSiapSvc; + svc->type = SVC_SIAP; + } else if (strncasecmp (type, "ssap", 4) == 0 || + strncasecmp (type, "simplespec", 9) == 0) { + svc->func = &vot_callSsapSvc; + svc->type = SVC_SSAP; + } else if (strncasecmp (type, "tabularsky", 8) == 0 || + strstr (url, "vizier")) { + svc->func = &vot_callConeSvc; + svc->type = SVC_VIZIER; + } else { + svc->func = NULL; + svc->type = SVC_OTHER; + } + svc->index = svcIndex++; + + svcTail = svc; +} + + +int +vot_isSupportedSvc (char *type) +{ + if (strncasecmp (type, "cone", 4) == 0 || + strncasecmp (type, "catalog", 7) == 0) + return (1); + else if (strncasecmp (type, "sia", 3) == 0 || + strncasecmp (type, "simpleimage", 10) == 0) + return (1); + else if (strncasecmp (type, "ssap", 4) == 0 || + strncasecmp (type, "simplespec", 9) == 0) + return (1); + else if (strncasecmp (type, "tabularsky", 10) == 0) + return (1); + + if (type && (*type) == (char) 0) + return (0); + + return (0); +} + + +/**************************************************************************** +** Utility routines to print and count the service list. +*/ + +int +vot_countServiceList () +{ + register int i = 0; + Service *svc = svcList; + + if (nservices < 0) + return (nservices); + else if (!svc) + return (0); + else + while ((svc = svc->next)) i++; + + return (i+1); +} + +int +vot_printServiceList (FILE *fd) +{ + register int i = 0; + Service *svc = svcList; + + if (!svc) + return (0); + + fprintf (fd, "# Services queried: %d\n#\n", vot_countServiceList()); + fprintf (fd, "# %4s\t%-16.16s\t%s\n", "Id", "Name", "Title"); + do { + fprintf (fd, "%4d\t%-16.16s\t%s\n", i++, svc->name, svc->title); + } while ((svc = svc->next)); + + return (0); +} + +int +vot_printServiceVOTable (FILE *fd) +{ + Service *svc = svcList; + + if (!svc) + return (0); + + + /* Print the VOTable header. + */ + fprintf (fd, "\ + <?xml version=\"1.0\" encoding=\"utf-8\"?>\ + <VOTABLE ID=\"ID\" xmlns=\"http://www.ivoa.net/xml/VOTable/v1.1\">\ + <RESOURCE><TABLE>"); + + fprintf (fd, "\ + <FIELD datatype=\"char\" name=\"shortName\" arraysize=\"*\"/>\ + <FIELD datatype=\"char\" name=\"identifier\" arraysize=\"*\"/>\ + <FIELD datatype=\"char\" name=\"accessURL\" arraysize=\"*\"/>\ + <FIELD datatype=\"char\" name=\"title\" arraysize=\"*\"/>"); + + fprintf (fd, "<DATA><TABLEDATA>"); + + do { + fprintf(stderr,"<TR><TD>%s</TD><TD>%s</TD><TD>%s</TD><TD>%s</TD></TR>", + svc->name, svc->service_url, svc->identifier, svc->title); + } while ((svc = svc->next)); + + /* Close off the table output. + */ + fprintf (fd, "</TABLEDATA></DATA></TABLE></RESOURCE></VOTABLE>\n"); + + return (0); +} + + + +/****************************************************************************** +** Registry cache handling routines. +** +** *********** FIXME ************* +*/ + +#define C_EXPIRE 2592000 /* 30 days */ + + +/* Create the cache name from the resolver terms. +*/ +static char * +vot_regIsCached (char *id, char *type, char *bpass) +{ + char *fname = vot_regCacheName (id, type, bpass); + char *s, *line[SZ_LINE]; + struct stat st; + time_t now = time ((time_t)NULL); + FILE *fd; + + +return ((char *) NULL); /** FIXME -- CURRENTLY DISABLED */ + + if ((s = getenv("VOC_NO_CACHE"))) + return ((char *) NULL); + + if (access (fname, F_OK) == 0) { + /* Check first for an expired entry. + */ + stat (fname, &st); + if ((st.st_ctime - now) > C_EXPIRE) { + unlink (fname); + return ((char *) NULL); + } + + /* Now see whether the contents look valid. + */ + if ((fd = fopen (fname, "r")) != (FILE *) NULL) { + (void) fgets ((char *)line, SZ_LINE, fd); + (void) fgets ((char *)line, SZ_LINE, fd); + if (strncasecmp ("INDEF", (char *)line, 5) == 0) { + fclose (fd); + unlink (fname); + return ((char *)NULL); + } + fclose (fd); + } + + return ((char *) fname); + } + + return ((char *) NULL); +} + + +/* Fetch the cached data. +*/ +static char * +vot_regGetCacheResults (char *fname, int *nres) +{ + FILE *fd; + int nr, size; + char line[SZ_LINE], *results; + + memset (line, 0, SZ_LINE); + if ((fd = fopen (fname, "r")) != (FILE *) NULL) { + (void) fgets ((char *)line, SZ_LINE, fd); + sscanf ((char *)line, "%d %d\n", &nr, &size); + results = (char *) calloc (1, size+2); + + while (fgets ((char *)line, SZ_LINE, fd)) + strcat ((char *)results, (char *)line); + } + fclose (fd); + + *nres = nr; + return ((char *)results); +} + + +/* Create the cache name from the resolver terms. +*/ +static void +vot_regCacheResults (char *fname, char *results, int nres) +{ + FILE *fd; + + if (access (fname, F_OK) == 0) + unlink (fname); + if ((fd = fopen (fname, "w+")) != (FILE *) NULL) { + fprintf (fd, "%d %d\n%s", nres, (int)strlen(results), results); + fclose (fd); + } +} + + +/**************************************************************************** +** Create the cache name from the resolver terms. +*/ +static char * +vot_regCacheName (char *id, char *type, char *bpass) +{ + static char name[SZ_FNAME]; + char s1[SZ_FNAME], s2[SZ_FNAME], s3[SZ_FNAME]; + extern char *voc_getCacheDir (char *s); + + bzero (name, SZ_FNAME); /* Initialize strings */ + + strcpy (s1, vot_normalize (id)); + strcpy (s2, vot_normalize (type)); + strcpy (s3, vot_normalize (bpass)); + + sprintf (name, "%s/%s_%s_%s", voc_getCacheDir("regResolver"), s1, s2, s3); + + return (name); +} + + + +void +vot_readSvcFile (char *fname, int dalOnly) +{ + char tmpfile[SZ_FNAME]; + extern char *vot_copyStdin(); + + + bzero (tmpfile, SZ_FNAME); + + if (strcmp (fname, "-") == 0) { /* read from stdin */ + + strcpy (tmpfile, vot_copyStdin ()); + + /* Parse the input and unlink the temp file. + */ + vot_parseServiceList (tmpfile, dalOnly); + unlink (tmpfile); + + } else if (access (fname, R_OK) == 0) + vot_parseServiceList (fname, dalOnly); +} + diff --git a/vendor/voclient/voapps/lib/voTask.c b/vendor/voclient/voapps/lib/voTask.c new file mode 100644 index 00000000..df9f039e --- /dev/null +++ b/vendor/voclient/voapps/lib/voTask.c @@ -0,0 +1,856 @@ +/** + * VOTASK.C -- Utilities to run a VOApps task as a connected subprocess. + * + * @file voTask.c + * @author Mike Fitzpatrick + * @date 6/23/12 + * + * @brief Utilities to run a VOApps task as a connected subprocess. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdarg.h> +#include <setjmp.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <sys/select.h> +#include <sys/time.h> +#include <sys/types.h> +#include "voApps.h" + + +#define PARENT_READ rpipe[0] /* read from parent */ +#define CHILD_WRITE rpipe[1] /* write to parent */ +#define CHILD_READ wpipe[0] /* read from child */ +#define PARENT_WRITE wpipe[1] /* write to parent */ + +#ifdef ERR +#undef ERR +#endif +#ifdef OK +#undef OK +#endif +#define ERR 1 +#define OK 0 + +#define MAX_TASK_ARGS 64 + + +static int rpipe[2] = {-1, -1}; /* subprocess read pipes */ +static int wpipe[2] = {-1, -1}; /* subprocess write pipes */ +static int nr = 0; + + + +/* Internal procedures. + */ +static pid_t vo_taskExec (char *method, Task *apps, int argc, char *argv[]); +static int vo_taskWait (pid_t pid, size_t *len); +static void *vo_taskResult (pid_t pid, size_t len); +static void vo_taskReaper (int sig, int *arg1, int *arg2); +static size_t vo_taskRead (int fd, void *data, size_t len); +static size_t vo_taskWrite (int fd, void *data, size_t len); + +typedef void (*SIGFUNC)(); + + + + +/*****************************************************************************/ +/** Public procedures **/ +/*****************************************************************************/ + + +/** + * VO_RUNTASK -- Run a VOApps task as a connected subprocess. + * + * @brief Run a VOApps task as a connected subprocess. + * @fn int vo_runTask (char *method, Task *apps, int argc, char *argv[], + * size_t *len, void **result) + * + * @param method task name to call + * @param apps application table + * @param argc argument count + * @param argv argument vector + * @param len length of result object + * @param result pointer to result object + * @return status (0=OK, 1=ERR) + */ + +static int vo_signal_status = 0; +static int vo_exit_status = 0; +sigjmp_buf vo_env; + +int +vo_runTask (char *method, Task *apps, int argc, char **argv, size_t *len, void **result) +{ + pid_t pid; + int status = 0, retStatus = EXIT_SUCCESS; + size_t resLen = 0; + void *res = (void *) NULL; + static SIGFUNC old_sigcld; + char err[128]; + + + memset (err, 0, 128); + + old_sigcld = (SIGFUNC) signal (SIGCHLD, (SIGFUNC) vo_taskReaper); + vo_signal_status = 0; + vo_exit_status = 0; + + sigsetjmp (vo_env, 1); + if (vo_signal_status || vo_exit_status) { + if (vo_signal_status) + sprintf (err, "Child exited with SIGNAL %d", vo_signal_status); + else if (vo_exit_status > 1) + sprintf (err, "Child exited with status %d", vo_exit_status); + *len = strlen (err); + *result = (void *) strdup (err); + + return (EXIT_FAILURE); + } + + if ((pid = vo_taskExec (method, apps, argc, argv)) > 0) { + + if ((status = vo_taskWait (pid, &resLen)) == EXIT_SUCCESS) { + + if (resLen && (res = vo_taskResult (pid, resLen))) + *result = res; /* save result from client */ + else + *result = (void *) NULL; /* no result from client */ + *len = resLen; + + } else { + sprintf (err, "Child exited with status %d", status); + *len = strlen (err); + *result = (void *) strdup (err); + return ( status ); /* child exits with error */ + } + + close (CHILD_WRITE); /* Close descriptors */ + close (CHILD_READ); + + } else { + fprintf (stderr, "Error executing task\n"); + retStatus = EXIT_FAILURE; + } + + signal (SIGCHLD, old_sigcld); /* reset the SIGCHLD handler */ + return (retStatus); +} + + +/** + * VO_TASKTEST -- Execute a task as a unit test. + * + * @brief Execute a task as a unit test. + * @fn int vo_taskTest (Task *self, char *arg, ...) + * + * @param self task struct pointer + * @param arg first of variable arg list + * @return status (0=OK, 1=ERR) + */ +int +vo_taskTest (Task *self, char *arg, ...) +{ + int i, status = OK, argc = 0; + char *argv[MAX_TASK_ARGS], *aval = NULL; + size_t reslen = 0; + void *result = (void *) NULL; + va_list argp; + + extern int optind; +#ifdef Darwin + extern int optreset; +#endif + + va_start (argp, arg); /* initialize */ + memset (argv, 0, sizeof (char *) * MAX_TASK_ARGS); + + optind = 0; /* required for unit test */ +#ifdef Darwin + optreset = 1; /* required for unit test */ +#endif + + /* Turn the varargs list into an argv[] we can pass to the task. + */ + argc = 1; + argv[0] = strdup (self->name); + + if (arg) { + argv[1] = strdup (arg); + for (i=2; (aval = (char *)va_arg(argp,char *)) != NULL; i++) { + if (aval) + argv[i] = strdup (aval); + } + argc = i; + va_end (argp); + } + + + /* Initialize the test output.... + */ + fprintf (stderr, "\n======================================="); + fprintf (stderr, "======================================\n"); + fprintf (stderr, "== Test Cmd: %s ", self->name); + for (i=1; i < argc; i++) + fprintf (stderr, "%s ", argv[i]); + fprintf (stderr, "\n\n"); + + + /* Execute the task, throw away any returned value. + */ + if (!getenv ("VOAPP_CONNECTED")) + status = vo_runTask (self->name, self, argc, argv, &reslen, &result); + else + status = (*(self->func)) (argc, argv, &reslen, &result); + + fprintf (stderr, "==================================="); + fprintf (stderr, "============================= status = %2d\n", status); + +vo_taskDbg(); + + /* Clean up. + */ + for (i=0; i < argc; i++) { + if (argv[i]) + free (argv[i]); + } + + if (status && result) /* print the error message */ + fprintf (stderr, "%s\n", (char *) result); + if (reslen && result) /* free result pointer */ + free (result); + + self->ntests++; /* update testing struct */ + if (status) + self->nfail++; + else + self->npass++; + + return (status); +} + + +/** + * VO_TASKDBG -- Tasking debug breakpoint. + * + * @brief Tasking debug breakpoint. + * @fn void vo_taskDbg (void) + * + * @return nothing + */ +void vo_taskDbg (void) +{ + static int i = 0; + + i++; +} + + +/** + * VO_TASKTESTREPORT -- Report from the task testing interface. + * + * @brief Report from the task testing interface. + * @fn void vo_taskTestReport (self) + * + * @param self task struct pointer + * @return status (0=OK, 1=ERR) + */ +void +vo_taskTestReport (Task self) +{ + fprintf (stderr, "\n"); + fprintf (stderr, + "Task: %-12.12s No. of Tests: %d Passed: %d Failed: %d\n", + self.name, self.ntests, self.npass, self.nfail); + + fprintf (stderr, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + fprintf (stderr, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); +} + + +/** + * VO_TASKTESTFILE -- Create a small named test file. + * + * @brief Create a small named test file. + * @fn void vo_taskTestFile (char *str, char *fname) + * + * @param str test string + * @param fname test filename + * @return status (0=OK, 1=ERR) + */ +void +vo_taskTestFile (char *str, char *fname) +{ + FILE *fd = (FILE *) NULL; + + if (access (fname, F_OK) == 0) + unlink (fname); + if ((fd = fopen (fname, "w+"))) { + fprintf (fd, "%s", str); + fclose (fd); + } +} + + +/** + * VO_SETRESULTFROMFILE -- Set a result object to a file's contents. + * + * @brief Set a result object to a file's contents. + * @fn int vo_setResultFromFile (char *fname, size_t *len, void **data) + * + * @param fname file name to read + * @param len length of result object + * @param data pointer to result object + * @return status (0=OK, 1=ERR) + */ +int +vo_setResultFromFile (char *fname, size_t *len, void **data) +{ + struct stat st; + int fd = 0; + + + if (stat (fname, &st) < 0) + return (ERR); + + if ((fd = open (fname, O_RDONLY)) > 0) { + *len = st.st_size; + *data = calloc (1, st.st_size + 1); + if (vo_taskRead (fd, *data, *len) < *len) + return (ERR); + close (fd); + } else + return (ERR); + + return (OK); +} + + +/** + * VO_SETRESULTFROMINT -- Set a result object to an int value. + * + * @brief Set a result object to an int value. + * @fn int vo_setResultFromInt (int value, size_t *len, void **data) + * + * @param value value to set + * @param len length of result object + * @param data pointer to result object + * @return status (0=OK, 1=ERR) + */ +int +vo_setResultFromInt (int value, size_t *len, void **data) +{ + char buf[SZ_FNAME]; + + memset (buf, 0, SZ_FNAME); + sprintf (buf, "%d", value); + + *len = strlen (buf); + *data = (char *) calloc (1, *len + 1); + strcpy ((char *) data, buf); + return (OK); +} + + +/** + * VO_SETRESULTFROMREAL -- Set a result object to a real value. + * + * @brief Set a result object to a real value. + * @fn int vo_setResultFromReal (float value, size_t *len, void **data) + * + * @param value value to set + * @param len length of result object + * @param data pointer to result object + * @return status (0=OK, 1=ERR) + */ +int +vo_setResultFromReal (float value, size_t *len, void **data) +{ + char buf[SZ_FNAME]; + + memset (buf, 0, SZ_FNAME); + sprintf (buf, "%g", value); + + *len = strlen (buf); + *data = (char *) calloc (1, *len + 1); + strcpy ((char *) data, buf); + return (OK); +} + + +/** + * VO_SETRESULTFROMSTRING -- Set a result object to a string value. + * + * @brief Set a result object to a string value. + * @fn int vo_setResultFromString (char *str, size_t *len, void **data) + * + * @param value value to set + * @param len length of result object + * @param data pointer to result object + * @return status (0=OK, 1=ERR) + */ +int +vo_setResultFromString (char *str, size_t *len, void **data) +{ + if (str) { + *len = strlen (str); + *data = (char *) calloc (1, *len + 1); + strcpy ((char *) *data, str); + } else { + *len = 0; + *data = NULL; + } + return (OK); +} + + +/** + * VO_APPENDRESULTFROMSTRING -- Append a result object to a string value. + * + * @brief Append a result object to a string value. + * @fn int vo_appendResultFromString (char *str, size_t *len, + * void **data, size_t *maxlen) + * + * @param value value to set + * @param len length of result object + * @param data pointer to result object + * @param maxlen max length of result object + * @return status (0=OK, 1=ERR) + */ +int +vo_appendResultFromString (char *str, size_t *len, void **data, size_t *maxlen) +{ + int slen = strlen (str); + + if (str) { + *len += slen; + + /* Reallocate in case we overrun the data buffer. + */ + if ((*len) > (*maxlen)) { + char *new = (char *) calloc (1, (*maxlen) + SZ_LINE); + strcpy (new, *data); + free ((void *) *data); + *data = new; + } + + strcat ((char *) *data, str); + } + return (OK); +} + + + + +/*****************************************************************************/ +/** Private procedures **/ +/*****************************************************************************/ + + +static void +vo_taskReaper ( + int sig, /* signal which was trapped */ + int *arg1, /* not used */ + int *arg2 /* not used */ +) +{ + int status = 0, pid = 0; + + + vo_signal_status = vo_exit_status = 0; + + while ((pid = (int) waitpid ((pid_t) 0, &status, WNOHANG)) > 0) + if (status) { + if (status & 0xFF) + vo_signal_status = (status & 0xFF); + else if (status >> 8) + vo_exit_status = (status >> 8); + siglongjmp (vo_env, 1); + } +} + + +/** + * VO_TASKEXEC -- Execute a task as a connected subprocess. + * + * @brief Get the result object (if any) from the task. + * @fn Task *vo_taskExec (char *method, Task *apps, int argc, char *argv[]) + * + * @param method task name to call + * @param apps task application table + * @param argc argument count + * @param argv argument vector + * @return pid of child process + */ + +#define GO_MSG "__go__" +#define GO_LEN 6 +#define E_NOTFOUND "Task not found" + +static pid_t +vo_taskExec (char *method, Task *apps, int argc, char **argv) +{ + Task *app = (Task *) NULL; + int status = 0; + pid_t cpid; + size_t resLen = 0; + void *result = (void *) NULL; + char msg[128]; + + + /* Create the pipes to/from the child process. + */ + if (pipe (rpipe) < 0 || pipe (wpipe) < 0) { + perror ("pipe failure"); + _exit (EXIT_FAILURE); + } + + + /* Fork so the child does all the work. + */ + if ( (cpid = fork ()) < 0 ) + return (cpid); + + if (cpid == 0) { /* Child */ + + close (CHILD_WRITE); /* Close unused descriptors */ + close (CHILD_READ); + + /* Wait for the '_go_' message. + */ + do { + memset (msg, 0, 128); + nr = vo_taskRead (PARENT_READ, msg, GO_LEN); + } while (strncmp (msg, GO_MSG, GO_LEN) != 0); + + + /* Loop through the application table. If the names match, call + * the entry-point function. + */ + for (app = apps; app->name; app++) { + if (strcmp (app->name, method) == 0) { + status = (*app->func)(argc, argv, &resLen, &result); + + /* Send the parent the status reply,result length and + * the result object, if there is one. + */ + vo_taskWrite (PARENT_WRITE, &status, sizeof (int)); + vo_taskWrite (PARENT_WRITE, &resLen, sizeof (size_t)); + if (resLen) + vo_taskWrite (PARENT_WRITE, result, resLen); + break; + } + } + + + /* If we get here, the task wasn't found. + */ + if (app->name == NULL) { + status = -1; + vo_taskWrite (PARENT_WRITE, &status, sizeof (int)); + vo_taskWrite (PARENT_WRITE, E_NOTFOUND, strlen (E_NOTFOUND)); + } + + /* Exit the child process. + */ + close (PARENT_READ); /* Close descriptors */ + close (PARENT_WRITE); + _exit (EXIT_SUCCESS); /* child exits */ + + } else { /* Parent */ + close (PARENT_READ); /* Close unneded descriptors */ + close (PARENT_WRITE); + + vo_taskWrite (CHILD_WRITE, GO_MSG, GO_LEN); + + return (cpid); + } +} + + +/** + * VO_TASKWAIT -- Wait for a child process to complete. + * + * @brief Wait for a child process to complete. + * @fn int vo_taskWait (pid_t pid, int *len) + * + * @param pid child process pid + * @param len length of result object + * @return exit status of child process + */ +static int +vo_taskWait (pid_t pid, size_t *len) +{ + int status = 0; + + + /* Wait for status message. + */ + vo_taskRead (CHILD_READ, &status, sizeof (int)); + vo_taskRead (CHILD_READ, len, sizeof (size_t)); + + wait (NULL); /* Wait for child */ + return (status); +} + + +/** + * VO_TASKRESULT -- Get the result object (if any) from the task. + * + * @brief Get the result object (if any) from the task. + * @fn void *vo_taskResult (pid_t pid, size_t len) + * + * @return (allocated) pointer to the Task + */ +static void * +vo_taskResult (pid_t pid, size_t len) +{ + void *result = (void *) calloc (1, len); + + vo_taskRead (CHILD_READ, result, len); + + return (result); +} + + +#define SELWIDTH 32 + +/** + * VO_TASKREAD -- Read exactly "n" bytes from a task descriptor. + * + * @brief Read exactly "n" bytes from a task descriptor. + * @fn size_t vo_taskRead (int fd, void *vptr, size_t nbytes) + * + * @param fd file descriptor + * @param vptr data buffer to be written + * @param nbytes number of bytes to write + * @return number of bytes written + */ +static size_t +vo_taskRead (int fd, void *vptr, size_t nbytes) +{ + char *ptr = vptr; + int nread = 0, nleft = nbytes, nb = 0, flags = 0; + fd_set allset, fds; + struct timeval tm = { 2, 0 }; + + + /* Set non-blocking mode on the descriptor. + */ + if ((flags = fcntl (fd, F_GETFL, 0)) == 0) + if (fcntl (fd, F_SETFL, flags | O_NONBLOCK) < 0) + ; /* ignore error */ + + FD_ZERO (&allset); + FD_SET (fd, &allset); + + while (nleft > 0) { + memcpy (&fds, &allset, sizeof(allset)); + if (select (SELWIDTH, &fds, NULL, NULL, &tm)) { + if ( (nb = read (fd, ptr, nleft)) < 0) { + if (errno == EINTR || errno == EAGAIN) + nb = 0; /* and call recv() again */ + else + return (-1); + } else if (nb == 0) + break; /* EOF */ + nleft -= nb; + ptr += nb; + nread += nb; + } + } + + return (nread); /* return no. of bytes read */ +} + + +/** + * VO_TASKWRITE -- Write exactly "n" bytes to a task descriptor. + * + * @brief Send exactly "n" bytes to a task descriptor. + * @fn size_t vo_taskWrite (int fd, void *vptr, size_t nbytes) + * + * @param fd file descriptor + * @param vptr data buffer to be written + * @param nbytes number of bytes to write + * @return number of bytes written + */ +static size_t +vo_taskWrite (int fd, void *vptr, size_t nbytes) +{ + char *ptr = vptr; + int nwritten = 0, nleft = nbytes, nb = 0, flags = 0; + fd_set allset, fds; + struct timeval tm = { 2, 0 }; + + + /* Set non-blocking mode on the descriptor. + */ + if ((flags = fcntl (fd, F_GETFL, 0)) == 0) + if (fcntl (fd, F_SETFL, flags | O_NONBLOCK) < 0) + ; /* ignore error */ + + FD_ZERO (&allset); + FD_SET (fd, &allset); + + while (nleft > 0) { + memcpy (&fds, &allset, sizeof(allset)); + if (select (SELWIDTH, NULL, &fds, NULL, &tm)) { + if ( (nb = write (fd, ptr, nleft)) <= 0) { + if (errno == EINTR || errno == EAGAIN) + nb = 0; /* and call write() again */ + else + return (-1); + } + nleft -= nb; + ptr += nb; + nwritten += nb; + } + } + + return (nwritten); +} + + + +#ifdef VO_UNIT_TESTS + +/************************************************************************/ + * Test Task declarations. + */ +int test_0 (int argc, char **argv, size_t *len, void **result); +int test_1 (int argc, char **argv, size_t *len, void **result); +int test_2 (int argc, char **argv, size_t *len, void **result); +int test_3 (int argc, char **argv, size_t *len, void **result); +int test_4 (int argc, char **argv, size_t *len, void **result); +int test_5 (int argc, char **argv, size_t *len, void **result); +int test_6 (int argc, char **argv, size_t *len, void **result); +int test_7 (int argc, char **argv, size_t *len, void **result); + +Task testApps[] = { + { "test0", test_0 }, /* test applications */ + { "test1", test_1 }, + { "test2", test_2 }, + { "test3", test_3 }, + { "test4", test_4 }, + { "test5", test_5 }, + { "test6", test_6 }, + { "test7", test_7 }, + { NULL, NULL }, +}; + + +/* Child doesn't return a result. + */ +int test_0 (int argc, char **argv, size_t *len, void **result) +{ + return (0); +} + +/* Child returns an error code. + */ +int test_1 (int argc, char **argv, size_t *len, void **result) +{ + return (1); +} + +/* Child returns a result. + */ +int test_2 (int argc, char **argv, size_t *len, void **result) +{ + char *str = strdup ("this is a test reply object"); + + *len = strlen (str); + if (*result == NULL) + *result = calloc (1, strlen (str) + 1); + strcpy ((char *) *result, str); + + free (str); + return (0); +} + +/* Child exits with status code + */ +int test_3 (int argc, char **argv, size_t *len, void **result) +{ + _exit (5); +} + +/* Child exits w/ FPE + */ +int test_4 (int argc, char **argv, size_t *len, void **result) +{ + int i=1, j=0, k = 0; + k = i / j; +} + +/* Child exits w/ segfault + */ +int test_5 (int argc, char **argv, size_t *len, void **result) +{ + char *foo = NULL; + strcpy (foo, "bar"); +} + +/* Child exits w/ SIGINT + */ +int test_6 (int argc, char **argv, size_t *len, void **result) +{ + raise (SIGINT); +} + +/* Multiple children.... + */ +int test_7 (int argc, char **argv, size_t *len, void **result) +{ + pid_t pid; + + if ((pid = fork()) < 0) + perror ("fork fails"); + else if (pid == 0) + raise (SIGILL); /* child */ + else { + sleep (1); wait (NULL); return (0); + } +} + + +/** + * Program entry point. + */ +int +main (int argc, char *argv[]) +{ + runTest ("test0", argc, argv); + runTest ("test1", argc, argv); + runTest ("test2", argc, argv); + runTest ("test3", argc, argv); + runTest ("test4", argc, argv); + runTest ("test5", argc, argv); + runTest ("test6", argc, argv); + runTest ("test7", argc, argv); + + return (0); +} + +int runTest (char *task, int argc, char **argv) +{ + int status = 0, len = 0; + void *res = (void *) NULL; + + fprintf (stderr, "Running '%s' .... ", task); + status = vo_runTask (task, argc, argv, &len, &res); + fprintf (stderr, "status=%d len=%d res='%s'\n", status, len, (char *)res); + if (res) + free (res); +} + +#endif /* VO_UNIT_TESTS */ diff --git a/vendor/voclient/voapps/lib/voUtil.c b/vendor/voclient/voapps/lib/voUtil.c new file mode 100644 index 00000000..d367cf54 --- /dev/null +++ b/vendor/voclient/voapps/lib/voUtil.c @@ -0,0 +1,2389 @@ +/**************************************************************************** +** VOUTIL.C -- Utility procedures for the VO-CLI tasks. +** +** M. Fitzpatrick, NOAO, June 2007 +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#include <unistd.h> +#include <ctype.h> +#include <string.h> +#include <time.h> + +#include <curl/curl.h> +#include <curl/types.h> +#include <curl/easy.h> + +#include "VOClient.h" +#include "votParse.h" +#include "voAppsP.h" +#include "voApps.h" + + +#define SZ_RESBUF (256*256) +#define SZ_QUERY 40960 +#define SZ_QSTRING 40960 + +#define DEF_RESATTR "ServiceURL" +#define MAX_ATTRS 32 + +static int reg_nresolved = 0; + + +extern int verbose, count, debug, errno, meta, res_all, quiet, do_votable; +extern int group, nterms, table_hskip, ecols; +extern char *terms[], *delim; + + +int vot_regResolver (char *id, char *svctype, char *bpass, char *subject, + char *clevel, char *fields, int index, int exact, + int dalOnly, char **result); +int vot_regSearch (char **ids, int nids, char *svctype, char *bpass, + char *subject, char *clevel, int orValues, + int votable, FILE *vot_fd, + int dalOnly, int sortRes, int terse); + + +void pretty_print (char *result, int nresults); +void pretty_print_table (char *result, int nresults, char *fields); +void ppMultiLine (char *result, int poffset, int pwidth, int maxchars); +void ppResSummary (char *result, int nresults); + +void vot_skipHdr (FILE *fd); +char *vot_getTableCol (char *line, int col, int span); +int vot_isNumericField (handle_t field); +int vot_fileType (char *fname); + +char *vot_urlFname (char *url); +void vot_printAttrs (char *fname, Query query, char *id); + +char *vot_parseSvcType (char *svctype, int exact); +char *vot_parseBandpass (char *bpass); +char *vot_parseSubject (char *subject); +char *vot_parseCLevel (char *level); +char *vot_mktemp (char *root); +char *vot_copyStdin (void); + +/* Utility procedures. +*/ +int isVOTable (char *fname); +int isSexagesimal (char *str); +int isDecimal (char *str); +float sexa (char *s); +char *toSexa (double pos); +char *toSexaTime (int nsec); +char *xmlEncode (char *in); + +int vot_atoi (char *val); +long vot_atol (char *val); +double vot_atof (char *val); + +void vot_setArg (char **argv, int *argc, char *value); +void vot_printRegVOTableHdr (FILE *fd); +void vot_printRegVOTableRec (FILE *fd, RegResult resource, int recnum); +void vot_printRegVOTableTail (FILE *fd); + +extern char *strcasestr (); + + + + +/**************************************************************************** +** Resolve a (presumed) ShortName or Identifier string to one or more +** Registry resource attributes. By default we assume we are interested +** only in the ServiceURL, however optional arguments allow us to narrow +** the search to particular service types or individual records. Examples: +** +** 1) Find the ServiceURL for the GSC2.2 catalog +** +** cl> =regResolver ("GSC2.2") +** http://chart.stsci.edu/GSCVO/GSC22VO.jsp? +** cl> =nresolved() +** 2 # found more than one resource +** +** 2) Print the Title and ServiceType for each record found for USNO-B1: +** +** cl> print (regResolver ("USNO-B1","","ServiceType,Title",-1)) +** CONE USNO-B1 Catalogue +** SKYNODE USNO-B1 SkyNode from VizieR +** +** Note that in usage such as this we are still limited by the length +** of output permitted by the print() function (currently 32*SZ_LINE). +** +** 3) Get the ServiceURL for the USNO-B1 Skynode service: +** +** cl> =regResolver ("USNO-B1","skynode") +** http://cdsws.u-strasbg.fr/USNO-B1BasicSkyNode/services/BasicSkyNode +** +*/ + +int +vot_regResolver (char *term, char *svctype, char *bpass, char *subject, + char *clevel, char *fields, int index, int exact, + int dalOnly, char **res) +{ + int i, j, nreturns=0, nattrs=0, ret_attr_start=0, try_again=1; + int match=-1, istart, iend, recnum, alen, blen, bsize; + char *ip, *field_str = (char *)NULL; + char *attr_val=NULL, *attr_list[MAX_ATTRS], id[SZ_LINE]; + char qstring[SZ_QSTRING], *svcstr, *bpstr, *substr, *conlev, *buf; + char attr_str[SZ_LINE], sbuf[SZ_RESBUF]; + RegQuery query = 0; + RegResult resource = 0; + + + if (term[0]) { + bzero (id, SZ_LINE); + strcpy (id, term); + } + if (debug) + fprintf (stderr, "regResolver init: id='%s' type='%s'\n", + (id[0] ? id : "null"), (svctype ? svctype : "null")); + + /* Sanity checks. + */ + if (!id[0] && !svctype && !svctype[0]) { + fprintf (stderr, "regResolver(): Must specify 'id' or 'svctype'\n"); + return (0); + } + + bzero (qstring, SZ_QSTRING); + bzero (sbuf, SZ_RESBUF); + strcpy (attr_str, DEF_RESATTR); + + + /* Set the default attribute list we want from the query. + */ + attr_list[0] = "ShortName"; + attr_list[1] = "Identifier"; + attr_list[2] = "Title"; + attr_list[3] = "AccessUrl"; + nattrs = 4; + + /* Parse the fields argument if any. + */ + if (fields && fields[0]) { + /* If we were given a list of fields, assume we want only those + ** and in that particular order. + */ + ret_attr_start = nattrs; + + /* Split up the input 'fields' string for use in the attr_list. + */ + field_str = strdup (fields); + for (ip=field_str; *ip && nattrs < MAX_ATTRS; ) { + attr_list[nattrs++] = ip; + while (*ip && *ip != ',') + ip++; + if (*ip == ',') + *ip++ = '\0'; + else + break; + } + } else + ret_attr_start = nattrs - 1; /* return ServiceURL only */ + + + /* Now parse the service type and bandpass for extra constraints. + */ + svcstr = vot_parseSvcType (svctype, !res_all); + bpstr = vot_parseBandpass (bpass); + substr = vot_parseSubject (subject); + conlev = vot_parseCLevel (clevel); + + if (strcmp (id, "%") == 0) { + if (bpass || svctype || subject) { + + /* Protect against a French overload. + */ + if (!(subject || bpass) && + (strcasestr(svctype,"table") || + strcasestr(svctype,"tabular") || + strcasestr(svctype,"vizier"))) { + fprintf (stderr, "Warning: Query too large to process.\n"); + return (0); + } + + bzero (qstring, SZ_QSTRING); + if (bpstr) { /* add bandpass constraint */ + strcpy (qstring, bpstr); + } + if (svcstr) { /* add service constraint */ + if (qstring[0]) + strcat (qstring, " AND "); + strcat (qstring, svcstr); + } + if (substr) { /* add subject constraint */ + if (qstring[0]) + strcat (qstring, " AND "); + strcat (qstring, substr); + } + if (conlev) { /* add content constraint */ + if (qstring[0]) + strcat (qstring, " AND "); + strcat (qstring, conlev); + } + + /* Execute the query. */ + if (strcasestr (svcstr, "catalog")) + resource = voc_regSearch (qstring, "catalog", 0); + else + resource = voc_regSearch (qstring, NULL, 0); + + } else { + fprintf (stderr, "Warning: Query too large to process.\n"); + return (0); + } + + } else { + + /* Lastly, set the query string we'll be using. + */ +retry: + if (group) { + for (i=0; i < nterms; i++) { + strcat (qstring, terms[i]); + if (i < (nterms -1)) + strcat (qstring, " OR "); + } + } else if (id[0]) { + char term[SZ_LINE], *ip, *op; + + memset (term, 0, SZ_LINE); + for (ip=id, op=term; *ip && *ip != '#'; ) + *op++ = *ip++; + + if (exact) { + sprintf (qstring, + "((Identifier like '%s') OR (ShortName like '%s'))", + term, term); + } else { + sprintf (qstring, + "((Identifier like '%%%s%%') OR (ShortName like '%%%s%%'))", + term, term); + } + } + + /* Do the registry query. Add the service-specific part of the query + ** once we get a handle. + */ + query = voc_regQuery (qstring, 0); + if (bpass && bpass[0]) { + voc_regAddSearchTerm (query, bpstr, 0); + voc_regConstWaveband (query, bpass); + } + if (svctype && svctype[0]) { + voc_regAddSearchTerm (query, svcstr, 0); + voc_regConstSvcType (query, svctype); + } + if (substr && substr[0]) + voc_regAddSearchTerm (query, substr, 0); + if (conlev && conlev[0]) + voc_regAddSearchTerm (query, conlev, 0); + if (dalOnly) + voc_regDALOnly (query, dalOnly); + + if (debug) { + printf ("regResolver: id='%s' type='%s' fields='%s' index=%d\n", + (id[0] ? id : "null"), + (svctype ? svctype : "null"), + (fields ? fields : "null"), index); + printf ("query string:\n\n%s\n\n", voc_regGetQueryString (query)); + } + + /* Execute the query. + */ + resource = voc_regExecute (query); + } + + blen = 0; /* length of result buffer used */ + + /* Save the number of resolved resources and get the requested attribute + * (or the default service URL). + */ + reg_nresolved = voc_resGetCount (resource); + if (reg_nresolved > 0) { + int isVizier = 0; + + bsize = (reg_nresolved * SZ_LINE); /* max size of result buffer */ + buf = (char *) calloc (1, bsize); + + if (do_votable) { + for (i=0; i < reg_nresolved; i++) + vot_printRegVOTableRec (stdout, resource, i); + + return (reg_nresolved); /* return number of matches found */ + } + + nreturns = (index >= 0 ? 1 : reg_nresolved); + + match = 0; + if (index >= 0 && reg_nresolved > 1) { + /* We didn't specify a record number but have more than one + * result. Look for an exact match in the ShortName or + * Identified which was a hidden part of the query. + */ + for (i=0; i < reg_nresolved; i++) { + for (j=0; j < 2; j++) { + if ((attr_val = voc_resGetStr(resource, attr_list[j], i))) { + if (strncasecmp (id, attr_val, strlen(attr_val)) == 0) { + reg_nresolved = 1; + nreturns = 1; + match = i; + break; + } + } + } + } + } + + if (index >= 0) { + istart = index; + iend = index + 1; + reg_nresolved = 1; + } else if (match >= 0 && nreturns == 1) { + istart = match; + iend = match + 1; + reg_nresolved = 1; + } else { + istart = 0; + iend = nreturns; + } + + /* For a negative index we list the attr for all records. + */ + recnum = 0; + if (dalOnly) + reg_nresolved = 0; + for (i=istart; i < iend; i++) { + isVizier = 0; + + if (dalOnly) { + int valid = 1; + for (j=ret_attr_start; j < nattrs; j++) { + if (strcmp (attr_list[j], "CapabilityStandardID") == 0) { + attr_val = voc_resGetStr (resource, attr_list[j], i); + if (attr_val) { + char *a = attr_val; + if (! (strncasecmp (a, "cone", 4) == 0 || + strncasecmp (a, "sia", 3) == 0 || + strncasecmp (a, "simpleimage", 10) == 0 || + strncasecmp (a, "ssap", 4) == 0 || + strncasecmp (a, "simplespec", 9) == 0)) { + valid = 0; + } else + reg_nresolved++; + } + break; + } + } + if (!valid) + continue; + } + + for (j=ret_attr_start; j < nattrs; j++) { + attr_val = voc_resGetStr (resource, attr_list[j], i); + if (strncasecmp (attr_list[j], "identifier", 10) == 0) + isVizier = (attr_val && strcasestr (attr_val, "vizier")); + if (attr_val) { + alen = strlen (attr_val); + strcat (buf, attr_val); + if (j < (nattrs-1)) + strcat (buf, "\t"); + voc_freePointer ((char *) attr_val); + } else { + alen = 0; + strcat (buf, (isVizier ? "Catalog\t" : "INDEF\t")); + } + + blen += max (alen, 10); + } + //if (nreturns > 1 && i < (reg_nresolved-1)) + if (nreturns > 1) + strcat (buf, "\n"); + + recnum++; + } + + attr_val = (char *) NULL; + + } else { + + if (try_again) { + if (strncasecmp("ivo://CDS.VizieR",id,16) == 0) { + char *ip, ivorn[SZ_LINE]; + int len = strlen (id); + + bzero (ivorn, SZ_LINE); + strcpy (ivorn, id); + for (ip = &ivorn[len-1]; *ip != '/'; ip--) + *ip = '\0'; + *ip = '\0'; + + strcpy (id, ivorn); + try_again = 0; + goto retry; + } + } + + buf = (char *) calloc (1, SZ_RESBUF); + for (j=0; j < nattrs; j++) { + strcpy (buf, "INDEF"); + if (j < (nattrs-1)) + strcat (buf, "\t"); + } + } + + if (field_str) free ((char *) field_str); /* free local memory */ + + /* Push the result operand on the return variable. We assume the result + ** is large enough for the value. + */ + *res = buf; + + if (bpstr) free (bpstr); + if (svcstr) free (svcstr); + if (substr) free (substr); + + if (debug) + printf ("regResolver: reg_nresolved = %d\n", reg_nresolved); + + return (reg_nresolved); /* return number of matches found */ +} + + +/**************************************************************************** +** Search the registry for the given phrase and constraints. +*/ +int +vot_regSearch (char **ids, int nids, char *svctype, char *bpass, + char *subject, char *clevel, int orValues, int votable, + FILE *vot_fd, int dalOnly, int sortRes, int terse) +{ + int i, nresults=0, nattrs=0, keywOnly = 1, haveADQL; + char *attr_val=NULL, *attr_list[MAX_ATTRS]; + char qstring[SZ_QUERY], keyws[SZ_RESBUF], *svcstr, *bpstr, *substr; + char term2[SZ_QUERY], *conlev; + char attr_str[SZ_LINE], *results, buf[SZ_LINE], cname[SZ_LINE]; + RegResult res = 0; + + + strcpy (attr_str, DEF_RESATTR); + + /* Set the default attribute list we want from the query. + */ + attr_list[0] = "Title"; + attr_list[1] = "CapabilityStandardID"; + attr_list[2] = "ShortName"; + attr_list[3] = "Subject"; + attr_list[4] = "Identifier"; + attr_list[5] = "ServiceUrl"; + attr_list[6] = "Description"; + + switch (verbose) { + case 0: nattrs = 4; break; + case 1: nattrs = 5; break; + case 2: nattrs = 7; break; + } + + + /* Now parse the service type and bandpass for extra constraints. + */ + svcstr = vot_parseSvcType (svctype, !res_all); + bpstr = vot_parseBandpass (bpass); + substr = vot_parseSubject (subject); + conlev = vot_parseCLevel (clevel); + + /* Begin forming the SQL query term we'll use + */ + bzero (qstring, SZ_QUERY); + bzero (term2, SZ_QUERY); + bzero (keyws, SZ_RESBUF); + + + /* Extract any terms that may be ADQL strings. + */ + for (i=0; i < nids; i++) { + if (strcasestr (ids[i], "like") || + strcasestr (ids[i], "<") || + strcasestr (ids[i], ">") || + strcasestr (ids[i], "=")) { + if (qstring[0] && orValues) + strcat (qstring, " OR "); + else if (qstring[0]) + strcat (qstring, " AND "); + sprintf (buf, "(%s)", ids[i]); + strcat (qstring, buf); + keywOnly = 0; + haveADQL = 1; + } + } + for (i=1; i < nids; i++) { + strcat (term2, ids[i]); + if (i < (nids-1)) + strcat (term2, " "); + } + + if (nids == 0 || (nids == 1 && strcmp ("any", *ids) == 0)) { + strcpy (qstring, "(Identifier like '%')"); + keywOnly = 0; + } + + + if (!keywOnly || nids == 0) { + if (svcstr) { /* add service constraint */ + if (qstring[0]) { + sprintf (buf, "(%s) AND (%s)", qstring, svcstr); + strcpy (qstring, buf); + } else { + strcat (qstring, svcstr); + } + } + if (bpstr) { /* add bandpass constraint */ + if (qstring[0]) { + sprintf (buf, "(%s) AND (%s)", qstring, bpstr); + strcpy (qstring, buf); + } else { + strcat (qstring, bpstr); + } + } + if (substr) { /* add subject constraint */ + if (qstring[0]) { + sprintf (buf, "(%s) AND (%s)", qstring, substr); + strcpy (qstring, buf); + } else { + strcat (qstring, substr); + } + } + if (conlev) { /* add subject constraint */ + if (qstring[0]) { + sprintf (buf, "(%s) AND (%s)", qstring, conlev); + strcpy (qstring, buf); + } else { + strcat (qstring, conlev); + } + } + } + + + /* Build a string arrays of the keyword terms. + */ + if (ids[0] && keywOnly) { + RegQuery query = (RegQuery) 0; + + if (nids == 0 || (nids == 1 && strcmp ("any", *ids) == 0)) { + strcpy (qstring, "(Identifier like '%')"); + query = voc_regQuery (qstring, FALSE); /* get a query object */ + + } else { + for (i=0; i < nids; i++) { + if (keyws[0]) + strcat (keyws, " "); + if (!strcasestr (ids[i], "like") && + !strcasestr (ids[i], "<") && + !strcasestr (ids[i], ">") && + !strcasestr (ids[i], "=")) + strcat (keyws, ids[i]); + } + query = voc_regQuery (keyws, orValues); /* get a query object */ + } + +#ifdef USE_CONSTRAINTS + if (svctype) /* set constraints */ + voc_regConstSvcType (query, svctype); + if (bpass) + voc_regConstWaveband (query, bpass); +#else + if (svcstr && svcstr[0]) + voc_regAddSearchTerm (query, svcstr, 0); + if (bpstr && bpstr[0]) + voc_regAddSearchTerm (query, bpstr, 0); +#endif + + if (substr && substr[0]) + voc_regAddSearchTerm (query, substr, 0); + if (conlev && conlev[0]) + voc_regAddSearchTerm (query, conlev, 0); + if (dalOnly) + voc_regDALOnly (query, dalOnly); + voc_regSortRes (query, sortRes); + + res = voc_regExecute (query); /* execute it */ + + } else { +/* + res = voc_regSearch (qstring, NULL, orValues); +*/ + res = voc_regSearch (qstring, term2, orValues); + bzero (keyws, SZ_RESBUF); + } + nresults = voc_resGetCount (res); + + + /* If no response, see if it was a ShortName used as a keyword term... + */ + if (nresults == 0 && !(svcstr || bpstr || substr || conlev) && !haveADQL) { + bzero (qstring, SZ_QUERY); + if (ids[0]) { + for (i=0; i < nids; i++) { + if (qstring[0]) + strcat (qstring, " OR "); + if (!strcasestr (ids[i], "like") && + !strcasestr (ids[i], "<") && + !strcasestr (ids[i], ">") && + !strcasestr (ids[i], "=")) { + sprintf (buf, + "(ShortName like '%s') OR (Identifier like '%s')", + ids[i], ids[i]); + strcat (qstring, buf); + } + } + } + + res = voc_regSearch (qstring, (nids ? keyws : NULL), 1); + + nresults = voc_resGetCount (res); + if (nresults && !count) { + verbose = 2; + } else if (nresults == 0) { + res = voc_regSearch (qstring, NULL, orValues); + nresults = voc_resGetCount (res); + } + } + + if (debug) + printf ("regSearch: qstr='%s' keyws='%s' nres = %d\n", + qstring, keyws, nresults); + + + /* No longer need the query buffers so free them here. + */ + if (svcstr) free (svcstr); + if (bpstr) free (bpstr); + if (substr) free (substr); + + + /* Return the result count if that's all we wanted. + */ + if (count) { + results = (char *)calloc (1, (nresults * 30)); + strcpy (results, " \t"); + for (i=0; i < nresults; i++) { + attr_val = voc_resGetStr (res, attr_list[1], i); /* SvcType */ + strcat (results, (attr_val ? attr_val : " ")); + strcat (results, "\t \n\t"); + voc_freePointer ((char *) attr_val); + } + if (keyws[0]) + printf ("%-20s %3d\t", keyws, nresults); + else + printf ("%d ", nresults); + if (verbose && !bpstr) + ppResSummary (results, nresults); + printf ("\n"); + + free ((char *) results); + return (nresults); + } + + + if (votable) { + for (i=0; i < nresults; i++) { + vot_printRegVOTableRec (vot_fd, res, i); + } + return (nresults); /* return number of matches found */ + } + + /* Print out the results for each resource based on the verbosity + ** level. + ** + ** Title: <title> ServiceType: <type> verb = 0 + ** ShortName: <name> Subject: <id> verb = 0 + ** Identifier: <id> ServiceURL: <url> verb = 1 + ** Description: <descr> verb = 2 + ** + */ + for (i=0; i < nresults; i++) { + + if (i > 0 && !terse) + printf ("-----------------------------------------------\n"); + + if (dalOnly) { /* CapName */ + attr_val = voc_resGetStr (res, "CapabilityName", i); + bzero (cname, SZ_LINE); + strcpy (cname, (attr_val ? attr_val : "")); + voc_freePointer ((char *) attr_val); + } + + if (terse) { + /* + int idx = voc_resGetInt (res, "index", i), + rank = voc_resGetInt (res, "rank", i); + + printf ("%2d(%2d) ", rank, idx); + */ + if (sortRes) + printf ("%3d %3d ", i, voc_resGetInt(res, "index", i) ); + + if (terse > 1) { + /* "Tweet" format. + */ + char *ip; + + printf ("New VO Resource: "); + + attr_val = voc_resGetStr (res, "Title", i); + printf ("\"%-s\" ", attr_val); + voc_freePointer ((char *) attr_val); + + attr_val = voc_resGetStr (res, "Waveband", i); + printf ("W:%s ", attr_val); + voc_freePointer ((char *) attr_val); + + attr_val = voc_resGetStr (res, "CapabilityStandardID", i); + printf ("T:%s ", attr_val); + voc_freePointer ((char *) attr_val); + + attr_val = voc_resGetStr (res, "Subject", i); + if (attr_val && (ip = strchr (attr_val, (int)':'))) + *ip = '\0'; /* kill qualifiers */ + printf ("S:%-s\n", attr_val); + voc_freePointer ((char *) attr_val); + + } else { + attr_val = voc_resGetStr (res, attr_list[1], i);/* SvcType */ + printf ("%-7.7s ", attr_val); + voc_freePointer ((char *) attr_val); + + attr_val = voc_resGetStr (res, attr_list[0], i);/* Title */ + printf ((sortRes ? "%-63.63s\n" : "%-71.71s\n"), attr_val); + voc_freePointer ((char *) attr_val); + } + + continue; + + } else { + attr_val = voc_resGetStr (res, attr_list[1], i); /* SvcType */ + printf (" Type: %-s\n", attr_val); + voc_freePointer ((char *) attr_val); + + attr_val = voc_resGetStr (res, attr_list[0], i); /* Title */ + printf (" Title: "); + ppMultiLine (attr_val, 13, 67, 1024); + printf ("\n"); + voc_freePointer ((char *) attr_val); + } + + attr_val = voc_resGetStr (res, attr_list[2], i); /* ShortName */ + if (dalOnly && verbose == 0) { + printf (" ShortName: %-s\n", attr_val); + printf ("ServiceName: %s\n", cname); + } else + printf (" ShortName: %-s\n", attr_val); + voc_freePointer ((char *) attr_val); + + attr_val = voc_resGetStr (res, attr_list[3], i); /* Subject */ + printf (" Subject: "); + ppMultiLine (attr_val, 13, 67, 1024); + printf ("\n"); + voc_freePointer ((char *) attr_val); + + if (verbose == 0) + continue; + + attr_val = voc_resGetStr (res, attr_list[4], i); /* Identifier */ + if (dalOnly) + printf (" Identifier: %-s#%s\n", attr_val, cname); + else + printf (" Identifier: %-s\n", attr_val); + voc_freePointer ((char *) attr_val); + + attr_val = voc_resGetStr (res, attr_list[5], i); /* ServiceUrl */ + printf (" ServiceURL: %-s\n", attr_val); + voc_freePointer ((char *) attr_val); + + if (verbose == 1) + continue; + + attr_val = voc_resGetStr (res, attr_list[6], i); /* Descr. */ + printf ("Description: "); + ppMultiLine (attr_val, 13, 67, 1024); + printf ("\n"); + voc_freePointer ((char *) attr_val); + } + + return (nresults); /* return number of matches found */ +} + + +/************************************************************************ +** PRETTY_PRINT -- Pretty-print a table for verbose resolution output. +*/ +void +pretty_print (char *result, int nresults) +{ + int i, j, ncols, col; + char *ip, value[SZ_RESULT]; + + + /* pretty-print the table using the defined widths. + */ + if (verbose) { + ip = result; + ncols = 3; + for (i=0; i < nresults; i++) { + j = 0; + for (col=0; col < ncols; ) { + bzero (value, SZ_RESULT); + while (*ip && (*ip != '\t' && *ip != '\n')) + value[j++] = *ip++; + + if (col == (ncols-1)) { + ppMultiLine (value, PP_OFFSET, PP_WIDTH, PP_MAXCHARS); + break; + } else + printf ("%-20s", value); + + j = 0; + col++; + ip++; + } + printf ("\n"); + ip++; + } + } else { + printf ("%s\n", result); + return; + } + +} + + +/************************************************************************ +** PPRESSUMMARY -- Print a summary of the resources found. Assumes the +** ServiceType is the second column of the result string. +*/ + +void +ppResSummary (char *result, int nresults) +{ + register int i, j; + int Ni = 0, /* image count */ + Nc = 0, /* catalog count */ + Nt = 0, /* table count */ + Ns = 0, /* spectra count */ + Nsn = 0, /* SkyNode count */ + Nother = 0; /* 'other' count */ + char *ip, value[SZ_RESULT]; + + + if (nresults == 0 || verbose == 1) + return; + + ip = result; + for (i=0; i < nresults; i++) { + bzero (value, SZ_RESULT); + while (*ip != '\t') ip++; /* skip first column */ + for (++ip, j=0; *ip != '\t';) /* gather the value */ + value[j++] = tolower (*ip++); + while (*ip && *ip != '\n') ip++; /* skip last column */ + ip++; + + if (strstr (value, "siap")) + Ni++; + else if (strstr (value, "cone")) + Nc++; + else if (strstr (value, "tabular")) + Nt++; + else if (strstr (value, "ssap")) + Ns++; + else if (strstr (value, "skynode") || strstr (value, "skyservice")) + Nsn++; + else + Nother++; + } + + printf ("("); + if (Nc) printf ("Cat: %-2d ", Nc); + if (Nt) printf ("Tab: %-2d ", Nt); + if (Ni) printf ("Img: %-2d ", Ni); + if (Ns) printf ("Spec: %-2d ", Ns); + if (Nsn) printf ("SNode: %-2d ", Nsn); + if (Nother) printf ("Other: %-2d", Nother); + printf (")"); +} + + + +/************************************************************************ +** PPMULTILINE -- Print a lengthy string on multiple lines. Used to print +** the last column of a table where we indent the carried-over lines to the +** specified offset. No effort is made to break lines at a 'nice' spot +** since long URLs and such won't fit anyway, so we just cut the line and +** continue. +*/ + +void +ppMultiLine (char *result, int poffset, int pwidth, int maxchars) +{ + register int i, j, ellipses = 0; + int len = strlen((result ? result : "")); + char *ip; + extern int longlines; + + if (result) + len = strlen (result); + else + return; + + + for (i=0; i < len-1; i++ ) { + if (result[i] == '\n' && result[i+1] != '\n') + result[i] = ' '; + } + + ip = &result[len-1]; /* strip trailing w/s */ + while ((isspace(*ip) || *ip == '\n') && ip > result) + *ip-- = '\0'; + + if (longlines) { + printf ("%s", result); + return; + } + + if (len > maxchars) { + result[maxchars] = '\0'; + len = maxchars; + ellipses++; + } + + if (len < pwidth) { + for (ip=result; *ip && isspace(*ip); ) + ip++; + printf ("%s", ip); + } else { + j = pwidth; + for (i=0; i < len; ) { + while (isspace (result[i])) i++; + + printf ("%-*.*s\n", pwidth, pwidth, &result[i]); + i = j + 1; + j += pwidth; + printf ("%*s", poffset, " "); + if (j > len) { + while (isspace (result[i])) i++; + printf ("%s", &result[i]); + if (ellipses) + printf (" (read more)...."); + break; + } + } + } +} + + +/************************************************************************ +** PRETTY_PRINT_TABLE -- Pretty-print a table with computed column widths. +*/ +void +pretty_print_table (char *result, int nresults, char *fields) +{ + int i, j, w, ncols, col, width[256]; + char *ip, value[SZ_RESULT]; + + + if (!result) + return; + if (!verbose && !fields) { + printf ("%s\n", result); + return; + } + + + /* Figure out how many columns there are. + */ + for (ip=result, ncols=1; *ip && *ip != '\n'; ip++) {/* do only 1st line */ + if (*ip && *ip == '\t') + ncols++; + } + + /* Calculate the column widths needed to align the columns. + */ + bzero (width, 256 * sizeof(int)); + ip = result; + for (i=0; i < nresults; i++) { + for (w=0, col=0; *ip; ) { + if (*ip == '\t' || *ip == '\n') { + if (w >= width[col]) + width[col] = w + 3; + w = 0; + col++; + } else + w++; + if (*ip++ == '\n') + break; + } + } + + + /* Now print the table using the computed widths. + */ + ip = result; + for (i=0; i < nresults; i++) { + j = 0; + bzero (value, SZ_RESULT); + for (col=0; col < ncols; ) { + if (!*ip || (*ip == '\t' || *ip == '\n')) { + value[j++] = '\0'; + if (col == (ncols-1)) + printf ("%-s", value); + else + printf ("%-*s", width[col], value); + j = 0; + col++; + } else + value[j++] = *ip; + if (*ip && *ip == '\n') + break; + ip++; + } + printf ("\n"); + ip++; + } +} + + + +/**************************************************************************** +** VOT_PARSESVCTYPE -- Parse the service type specification. Allow for +** synonyms like 'catalog' for 'cone', 'image' for 'siap', etc. +*/ +char * +vot_parseSvcType (char *svctype, int exact) +{ + char *ip, *op, val[SZ_FNAME], buf[SZ_FNAME]; + char *svcstr = NULL, *like = NULL; + int not = 0, more = 0; + + + like = (exact ? "" : "%"); /* initialize */ + + if (svctype && svctype[0]) { + svcstr = calloc (1, 4*SZ_LINE); + + strcat (svcstr, "("); + for (ip=svctype; *ip; ) { + more = 0; /* re-initialize */ + not = 0; + bzero (val, SZ_FNAME); + + for (op=val; *ip; ) { + if (*ip == '-') { + not++, ip++; + } else if (*ip == ',') { + more++, ip++; + break; + } else + *op++ = *ip++; + } + + /* Aliases for service type include: + ** + ** Cone -> catalog + ** SIAP -> image + ** TABULARSKYSERVICE -> table + ** SSAP -> spectrum + ** TAP -> query + */ + if (not) strcat (svcstr, "(!"); + + if (strncasecmp (val,"catalog",3) == 0) + strcat (svcstr, "(Tag like '%catalog%')"); + else if (strncasecmp (val,"image",5) == 0) + strcat (svcstr, "(Tag like '%image%')"); + else if (strncasecmp (val,"spectr",6) == 0) + strcat (svcstr, "(Tag like '%spec%')"); + else if (strncasecmp (val,"table",5) == 0) + strcat (svcstr, "(Identifier like '%Vizier%')"); + else { + bzero (buf, SZ_FNAME); + sprintf (buf, "(Tag like '%s%s%s')", like, val, like); + strcat (svcstr, buf); + } + + if (not) strcat (svcstr, ")"); + if (more) strcat (svcstr, " OR "); + } + strcat (svcstr, ")"); + + return (svcstr); + } + + return ((char *)NULL); +} + + + +/**************************************************************************** +** VOT_PARSEBANDPASS -- Convert a bandpass specification to an ADQL query. We +** map things like 'x-ray' and 'xray' here to expand the query on behalf of +** the user. +** +** Permitted values include: +** "Radio", "Millimeter", "Infrared" (IR), "Optical", "Ultraviolet" (UV), +** "X-Ray" (XRay), and "Gamma-Ray" (GR). +*/ +char * +vot_parseBandpass (char *bpass) +{ + char *ip, *op, val[SZ_FNAME], buf[SZ_FNAME]; + char *bpstr = NULL; + int not = 0, more = 0; + + + if (bpass && bpass[0]) { + bpstr = calloc (1, 6*SZ_LINE); + + strcat (bpstr, "("); + for (ip=bpass; *ip; ) { + more = 0; /* re-initialize */ + not = 0; + bzero (val, SZ_FNAME); + + for (op=val; *ip; ) { + if (*ip == '-' && strncasecmp(ip,"-ray",4)) { + not++, ip++; + } else if (*ip == ',') { + more++, ip++; + break; + } else + *op++ = *ip++; + } + + if (not) strcat (bpstr, "(!"); + + if (strncasecmp (val, "radio",3) == 0) + strcat (bpstr, "([coverage/waveband] like '%radio%')"); + else if (strncasecmp (val,"millimeter",9) == 0) + strcat (bpstr, "([coverage/waveband] like '%millimeter%')"); + else if (strncasecmp (val,"infrared",5) == 0 || + strncasecmp (val,"ir",2) == 0) + strcat (bpstr, "([coverage/waveband] like '%infrared%')"); + else if (strncasecmp (val,"optical",8) == 0) + strcat (bpstr, "([coverage/waveband] like '%optical%')"); + else if (strncasecmp (val,"ultraviolet",5) == 0 || + strncasecmp (val,"uv",2) == 0) + strcat (bpstr,"([coverage/waveband] like '%ultraviolet%')"); + else if (strncasecmp (val,"x-ray",5) == 0 || + strncasecmp (val,"xray",4) == 0) + strcat (bpstr, "([coverage/waveband] like '%x-ray%')"); + else if (strncasecmp (val,"gamma-ray",9) == 0 || + strncasecmp (val,"gammaray",8) == 0) + strcat (bpstr, "([coverage/waveband] like '%gamma-ray%')"); + else { + bzero (buf, SZ_FNAME); + sprintf (buf, "([coverage/waveband] like '%%%s%%')", val); + strcat (bpstr, buf); + } + + if (not) strcat (bpstr, ")"); + if (more) strcat (bpstr, " OR "); + } + strcat (bpstr, ")"); + + return (bpstr); + } + + return ((char *)NULL); +} + + +/**************************************************************************** +** VOT_PARSESUBJECT -- Convert a subject specification to an ADQL query +** string. We don't impose a vocabulary on the allowed Subject string, but +** do allow the string to be a comma-delimited list of subjects. +*/ +char * +vot_parseSubject (char *subject) +{ + char *ip, *op, val[SZ_FNAME], buf[SZ_FNAME]; + char *substr; + int more = 0; + + + substr = calloc (1, 6*SZ_LINE); + if (subject && subject[0]) { + strcat (substr, "("); + for (ip=subject; *ip; ) { + more = 0; /* re-initialize */ + bzero (val, SZ_FNAME); + + for (op=val; *ip; ) { + if (*ip == ',') { + more++, ip++; + break; + } else + *op++ = *ip++; + } + + bzero (buf, SZ_FNAME); + sprintf (buf, "([content/subject] like '%%%s%%')", val); + strcat (substr, buf); + + if (more) strcat (substr, " OR "); + } + strcat (substr, ")"); + + return (substr); + } + + return ((char *)NULL); +} + + +/**************************************************************************** +** VOT_PARSECLEVEL -- Convert a ContentLevel specification to an ADQL query +** string. +*/ +char * +vot_parseCLevel (char *level) +{ + char *ip, *op, *str, val[SZ_FNAME], buf[SZ_FNAME]; + int more = 0; + + str = calloc (1, 6*SZ_LINE); + if (level && level[0]) { + strcat (str, "("); + for (ip=level; *ip; ) { + more = 0; /* re-initialize */ + memset (val, 0, SZ_FNAME); + + for (op=val; *ip; ) { + if (*ip == ',') { + more++, ip++; + break; + } else + *op++ = *ip++; + } + + memset (buf, 0, SZ_FNAME); + sprintf (buf, "([content/contentLevel] like '%%%s%%')", val); + strcat (str, buf); + if (more) + strcat (str, " OR "); + } + strcat (str, ")"); + return (str); + } + + return ((char *)NULL); +} + + +/************************************************************************ +** Return the filename part of a URL. +*/ +char * +vot_urlFname (char *url) +{ + char *ip; + int len = strlen (url); + + for (ip=&url[len-1]; ip >= url; ip--) { + if (*ip == '&' || *ip == '?') + *ip = '\0'; + if (*ip == '/') + return (ip+1); + } + + return (ip); +} + + +/****************************************************************************** +** Print the resource attributes. +*/ +void +vot_printAttrs (char *fname, Query query, char *ident) +{ + char *result = (char *) NULL, *qstring = (char *) NULL; + int i=0, nrec, nattr; +#ifdef OLD_ATTRS + char *ip, *attrList = (char *) NULL; + QRecord rec = (QRecord) NULL; /* Query record */ + QResponse qr = (QResponse) NULL; /* Query response */ +#else + int vot = 0, nbytes = 0; + FILE *fd = stdout; + char *ip, *op; +#endif + + + + if (!query) { + fprintf (stderr, "# Query failed, returning\n"); + return; + } + +#ifdef OLD_ATTRS + if ((qr = voc_executeQuery (query))) { + rec = voc_getRecord (qr, 0); /* get a row in the table */ + nrec = voc_getRecordCount (qr); + } + nattr = (rec ? voc_getAttrCount (rec) : 0); + + if (nattr > 0) { + printf ("\n# --- Identifier: %s\n#\n", ident); + + if (!meta) + printf ("# returns %d records containing %d attributes each\n", + nrec, nattr); + + attrList = voc_getAttrList (rec); + printf ("# Col UCD\n"); + printf ("# --- ---\n# %2d ", (i=1)); + for (i++, ip=attrList; *ip; ip++) { + if (isspace (*ip)) + printf ("\n# %2d ", i++); + else + putchar (*ip); + } + printf ("\n#\n"); + + if (attrList) free ((void *) attrList); + } else + printf ("# --- No Attributes Found ---\n#\n"); + +#else + + if (query > 0) { + if (! (qstring = voc_getQueryString (query, DAL_CONN, 0))) + return; + } else + return; + + while (isspace (*qstring)) + qstring++; + + if ((ip = strcasestr (qstring, "format=image"))) { + op = ip; + while (*ip && *ip != '&') + ip++; + if (*ip) { + for (ip++; *ip ;) + *op++ = *ip++; + } + *op = '\0'; + } + + if ((result = voc_getRawURL (qstring, &nbytes)) == NULL) + return; + + /* FIXME -- rawURL still returns garbage at the end..... + result[nbytes] = '\0'; + */ + + if ( nbytes > 0 && (vot = vot_openVOTABLE (result)) > 0 ) { + + char ucd[SZ_FNAME], name[SZ_FNAME], desc[SZ_LINE], id[SZ_FNAME], *at; + extern char *vot_getFieldName(), *vot_getFieldDesc(); + extern char *vot_getFieldUCD(), *vot_getFieldID();; + + handle_t res, tab, data, tdata, field, handle; + + + res = vot_getRESOURCE (vot); /* get handles */ + if ((tab = vot_getTABLE (res)) <= 0) { + if ((data = vot_getDATA (tab)) <= 0) { + if ((tdata = vot_getTABLEDATA (data))) { + nrec = vot_getNRows (tdata); + nattr = vot_getNCols (tdata); + } + } + } + + + if (!fname || strcmp (fname, "-") == 0) { + fd = stdout; + } else { + if ((fd = fopen (fname, "w+")) == (FILE *) NULL) + return ; + } + + fprintf (fd, "\n Service: %s\n NAttrs: %d\n\n", + (ident ? ident : "N/A"), nattr); + fprintf (fd, + " Col UCD Name Description\n"); + fprintf (fd, + " --- --- ---- -----------------------\n"); + + for (i=1, field=vot_getFIELD (tab); field; field=vot_getNext (field)) { + + fprintf (fd, " %3d ", i++); + + memset (ucd, 0, SZ_FNAME); + memset (name, 0, SZ_FNAME); + memset (id, 0, SZ_FNAME); + memset (desc, 0, SZ_LINE); + + strcpy (ucd, ((at=vot_getAttr (field, "ucd")) ? at : "")); + strcpy (name, ((at=vot_getAttr (field, "name")) ? at : "")); + strcpy (id, ((at=vot_getAttr (field, "id")) ? at : "")); + + if ((handle = vot_getDESCRIPTION (field))) + strcpy (desc, vot_getValue (handle)); + else + strcpy (desc, " "); + +/* + strcpy (desc, ((at=vot_getAttr (field, "description")) ? at : "")); + + fprintf (fd, "%-27.27s ", (ucd[0] ? ucd : + (name[0] ? name : + (id[0] ? id : " "))) ); +*/ + fprintf (fd, "%-16.16s %-10.10s ", ucd, name); + + if (desc[0]) { + ppMultiLine (desc, 34, 45, 1024); + } else { + if (name[0] && strcmp (name, id) == 0) + fprintf (fd, "name=id='%s'", name); + else { + if (name[0]) + fprintf (fd, "name='%s'%s", name, (id[0] ? ", ":" ")); + if (id[0]) + fprintf (fd, "id='%s'", id); + } + } + + + fprintf (fd, "\n"); + } + vot_closeVOTABLE (vot); + + if (fd != stdout) + fclose (fd); + + } else if (!quiet) + fprintf (stderr, " %-50s Error\n", ident); + + +/* FIXME -- causes a segfault + if (result) + voc_freePointer ((char *) result); +*/ +#endif +} + + +/** + * VOT_SETARG -- Set a value in an argv vector, update the count. + */ +void +vot_setArg (char **argv, int *argc, char *value) +{ + int i = *argc; + + argv[i] = strdup (value); + *argc += 1; +} + + +/************************************************************************ +** PRINTVOTABLEHDR -- Print the prolog to the VOTable output. +*/ +void +vot_printRegVOTableHdr (FILE *fd) +{ +fprintf (fd, "\ +<?xml version=\"1.0\" encoding=\"utf-8\"?>\ +<VOTABLE ID=\"ID\" xmlns=\"http://www.ivoa.net/xml/VOTable/v1.1\">\ +<DESCRIPTION>REGISTRY SEARCH RESULTS</DESCRIPTION>\ +<RESOURCE>\ +<INFO name=\"QUERY_STATUS\" value=\"OK\"></INFO>\ +<TABLE>"); + +if (verbose == 0) { + +fprintf (fd, "\ +<FIELD datatype=\"char\" name=\"title\" arraysize=\"*\"/>\ +<FIELD datatype=\"char\" name=\"shortName\" arraysize=\"*\"/>\ +<FIELD datatype=\"char\" name=\"identifier\" arraysize=\"*\"/>\ +<FIELD datatype=\"char\" name=\"accessURL\" arraysize=\"*\"/>\ +<FIELD datatype=\"char\" name=\"referenceURL\" arraysize=\"*\"/>\ +<FIELD datatype=\"char\" name=\"capabilityClass\" arraysize=\"*\"/>\ +<FIELD datatype=\"char\" name=\"contentLevel\" arraysize=\"*\"/>\ +<FIELD datatype=\"char\" name=\"type\" arraysize=\"*\"/>\ +<FIELD datatype=\"char\" name=\"waveband\" arraysize=\"*\"/>\ +<FIELD datatype=\"char\" name=\"publisher\" arraysize=\"*\"/>\ +<FIELD datatype=\"char\" name=\"subject\" arraysize=\"*\"/>\ +<FIELD datatype=\"char\" name=\"version\" arraysize=\"*\"/>"); + +} else { + +fprintf (fd, "\ +<FIELD ID=\"tags\" datatype=\"char\" name=\"categories\" arraysize=\"*\"/>\ +<FIELD ID=\"shortName\" datatype=\"char\" name=\"shortName\" arraysize=\"*\"/>\ +<FIELD ID=\"title\" datatype=\"char\" name=\"title\" arraysize=\"*\"/>\ +<FIELD ID=\"description\" datatype=\"char\" name=\"description\" arraysize=\"*\"/>\ +<FIELD ID=\"publisher\" datatype=\"char\" name=\"publisher\" arraysize=\"*\"/>\ +<FIELD ID=\"waveband\" datatype=\"char\" name=\"waveband\" arraysize=\"*\"/>\ +<FIELD ID=\"identifier\" datatype=\"char\" name=\"identifier\" ucd=\"ID_MAIN\" arraysize=\"*\"/>\ +<FIELD ID=\"updated\" datatype=\"char\" name=\"descriptionUpdated\" arraysize=\"*\"/>\ +<FIELD ID=\"subject\" datatype=\"char\" name=\"subject\" arraysize=\"*\"/>\ +<FIELD ID=\"type\" datatype=\"char\" name=\"type\" arraysize=\"*\"/>\ +<FIELD ID=\"contentLevel\" datatype=\"char\" name=\"contentLevel\" arraysize=\"*\"/>\ +<FIELD ID=\"regionOfRegard\" unit=\"arcsec\" datatype=\"int\" name=\"typicalRegionSize\"/>\ +<FIELD ID=\"version\" datatype=\"char\" name=\"version\" arraysize=\"*\"/>\ +<FIELD ID=\"capabilityClass\" datatype=\"char\" name=\"capabilityClass\" arraysize=\"*\"/>\ +<FIELD ID=\"capabilityID\" datatype=\"char\" name=\"capabilityStandardID\" arraysize=\"*\"/>\ +<FIELD ID=\"capabilityValidationLevel\" datatype=\"char\" name=\"capabilityValidationLevel\" arraysize=\"*\"/>\ +<FIELD ID=\"interfaceClass\" datatype=\"char\" name=\"interfaceClass\" arraysize=\"*\"/>\ +<FIELD ID=\"interfaceVersion\" datatype=\"char\" name=\"interfaceVersion\" arraysize=\"*\"/>\ +<FIELD ID=\"interfaceRole\" datatype=\"char\" name=\"interfaceRole\" arraysize=\"*\"/>\ +<FIELD ID=\"accessURL\" datatype=\"char\" name=\"accessURL\" arraysize=\"*\"/>\ +<FIELD ID=\"supportedInputParam\" datatype=\"char\" name=\"supportedInputParam\" arraysize=\"*\"/>\ +<FIELD ID=\"maxRadius\" datatype=\"int\" name=\"maxSearchRadius\"/>\ +<FIELD ID=\"maxRecords\" datatype=\"int\" name=\"maxRecords\"/>\ +<FIELD ID=\"publisherID\" datatype=\"char\" name=\"publisherIdentifier\" arraysize=\"*\"/>\ +<FIELD ID=\"referenceURL\" datatype=\"char\" name=\"referenceURL\" arraysize=\"*\"/>"); +} +fprintf (fd, "<DATA><TABLEDATA>"); + +fflush (fd); +} + + +/************************************************************************ +** PRINTVOTABLEREC -- Print an individual record in the search results +** as a VOTable row. +*/ +void +vot_printRegVOTableRec (FILE *fd, RegResult resource, int recnum) +{ + register int i; + char *attr_val, *fmt, *attr; + + static char *resAttr[] = { + "Title", "ShortName", "Identifier", + "AccessURL", "ReferenceURL", "CapabilityClass", + "ContentLevel", "Type", "Waveband", + "Creator", "Subject", "Version", + NULL + }; + + static char *resAttrVerbose[] = { + "tags", "shortName", "title", + "description", "publisher", "waveband", + "identifier", "updated", "subject", + "type", "contentLevel", "regionOfRegard", + "version", "capabilityClass", "capabilityID", + "capabilityValidationLevel", "interfaceClass", + "interfaceVersion", "interfaceRole", "accessURL", + "supportedInputParam", "maxRadius", "maxRecords", + "publisherID", "referenceURL", + NULL + }; + + + + fprintf (fd, "<TR>"); + for (i=0; 1; i++) { + attr = (verbose ? resAttrVerbose[i] : resAttr[i]); + if (attr == NULL) + break; + + attr_val = xmlEncode (voc_resGetStr (resource, attr, recnum)); + + /* Escape any URLs to take care of special chars. + */ + fmt = (*attr_val && strstr(attr,"URL") ? + "<TD><![CDATA[%s]]></TD>" : "<TD>%s</TD>"); + + if (!(*attr_val) && + (strcmp (attr, "regionOfRegard") == 0 || + strcmp (attr, "maxRadius") == 0 || + strcmp (attr, "maxRecords") == 0)) { + fprintf (fd, fmt, "0"); + + } else if (attr_val && *attr_val) { + fprintf (fd, fmt, attr_val); + + } else + fprintf (fd, "<TD/>"); + + if (attr_val) + voc_freePointer ((char *) attr_val); + } + fprintf (fd, "</TR>"); + fflush (fd); +} + + + +/************************************************************************ +** PRINTVOTABLETAIL -- Print the epilog to the VOTable output. +*/ +void +vot_printRegVOTableTail (FILE *fd) +{ +fprintf (fd, "\ +</TABLEDATA>\ +</DATA>\ +</TABLE>\ +</RESOURCE>\ +</VOTABLE>\n"); +} + + + +/**************************************************************************** +** Lexical utility procedures. +*/ + +char * +xmlEncode (char *in) +{ + char *ip, *op, *out; + + if (in == (char *) NULL) + return (calloc(1,2)); /* caller will free this pointer */ + + out = calloc (1, strlen(in) * 2); + ip = in; + op = out; + + while (*ip) { + if (*ip == '<') { + strncpy (op, ">", 4); + op += 4; + } else if (*ip == '>') { + strncpy (op, ">", 4); + op += 4; + } else if (*ip == '&') { + strncpy (op, "&", 5); + op += 5; + } else if (*ip == '\'') { + strncpy (op, """, 6); + op += 6; + } else if (*ip == '\"') { + strncpy (op, "&dquot;", 7); + op += 7; + } else + *op++ = *ip; + + ip++; + } + + + if (in) + voc_freePointer ((char *) in); + + return (out); +} + + + +/************************************************************************ +** VOT_GETLINE -- Get the next line in a file/stdin. We use this procedure +** to allow for parsing input that may be piped in where newlines are +** expressed as the string "\n". +*/ +char * +vot_getline (FILE *fd) +{ + int i, ch, peek; + static char cmdline[SZ_LINE]; + + + bzero (cmdline, SZ_LINE); + + for (i=ch=0; ch != EOF; i++) { + cmdline[i] = ch = (char) fgetc (fd); + if (i == 0 && ch == EOF) + return (NULL); + else if (i > 0 && (ch == EOF || ch == '\n')) { + cmdline[i] = '\0'; + break; + } else if (ch == (int) '\\') { + if ((peek = fgetc (fd)) == (int)'n') { + cmdline[i] = '\0'; + break; + } else + ungetc (peek, fd); + } + } + + return (cmdline); +} + + +/**************************************************************************** +** NORMALIZECOORD -- Normalize a coordinate string, i.e. strip whitespace +** from the ends and replace internal whitespace with a ':' in the case of +** sexagesimal values. +*/ +char * +vot_normalizeCoord (char *coord) +{ + static char *ip, *op, norm[SZ_LINE]; + + + bzero (norm, SZ_LINE); + + /* Remove trailing whitespace */ + for (ip=&coord[strlen(coord)-1]; isspace(*ip) && ip > coord; ) + *ip = '\0'; + + /* Skip leading whitespace */ + for (ip=coord; *ip && isspace(*ip); ip++) + ; + + for (op=norm; *ip; ) { + if (isspace (*ip)) { + *op++ = ':'; + while (*ip && isspace(*ip)) /* collapse multiple space */ + ip++; + } else + *op++ = *ip++; + } + + return (norm); +} + + +/**************************************************************************** +** Normalize the names, i.e. replace anything other than [.+-] with '-'. +*/ +char * +vot_normalize (char *str) +{ + char *ip, *op; + static char name[SZ_FNAME]; + + if (str == (char *)NULL) + return (""); + + bzero (name, SZ_FNAME); + for (ip=str, op=name; *ip; ) { + if (strchr (".+-", (int)*ip)) + *op++ = *ip++; + else if (!isalnum ((int)*ip)) + *op++ = '-', ip++; + else + *op++ = *ip++; + } + + return (name); +} + + + +/* UTILITY FUNCTIONS. +*/ + +/**************************************************************************** +** ISVOTABLE -- Test a file or string to see if it's a VOTable. +*/ +int +isVOTable (char *fname) +{ + int i; + FILE *fd = (FILE *) NULL; + char line[SZ_LINE]; + + if (fname[0] == '-') { + (void) fgets (line, SZ_LINE, stdin); + if (line[0] == '<') + return (1); + + } else if (access (fname, R_OK) == 0) { + + /* Process the file contents. + */ + if ((fd = fopen (fname, "r")) == (FILE *) NULL) { + fprintf (stderr, "ERROR: Cannot open file '%s'\n", fname); + return (0); + } + + for (i=0; i < 10 && fgets (line, SZ_LINE, fd); i++) { + if (strcasestr (line, "VOTABLE")) { + fclose (fd); + return (1); + } + } + + if (fd) + fclose (fd); + } + + return (0); +} + + +int +isSexagesimal (char *str) +{ + register int i; + + /* Allow only numbers, colons, decimal point, whitespace, and sign. */ + for (i=(strlen(str)-1); i >= 0; i--) + if (!isdigit(str[i]) && strchr("/:+- .\t,", (int)str[i])==(char *)NULL) + return (0); + + return (1); +} + +int +isDecimal (char *str) +{ + register int i; + + /* Allow only numbers, decimal point, whitespace, and sign. */ + for (i=(strlen(str)-1); i >= 0; i--) + if (!isdigit(str[i]) && strchr("/+- .\t,", (int)str[i])==(char *)NULL) + return (0); + + return (1); +} + +float +sexa (char *s) +{ + int n, sign; + int hr, minutes; + float sec, val; + extern double atof(); + + while (isspace (*s)) /* skip leading whitespace */ + s++; + sign = (*s == '-') ? (s++, -1) : 1; /* get the sign */ + + minutes = 0; + sec = 0.; + n = sscanf (s, "%d:%d:%f", &hr, &minutes, &sec); + if (n < 1 || minutes < 0 || sec < 0) + val = -999.0; + else + /* Beware: Evaluation here can produce roundoff errors! + */ + val = sign * (hr + ((float)minutes)/60. + sec/3600.); + + return (val); +} + + +char * +toSexa (double pos) +{ + static char str[SZ_LINE]; + int d, m; + float s, frac; + char sign = (pos < 0.0 ? '-' : 0); + + + pos = (pos < 0.0 ? -pos : pos); + + d = (int) pos; + frac = (pos - d); + m = frac * 60.0; + s = ((frac * 60.0) - m) * 60.0; + + if (sign) + sprintf (str, "%c%02d:%02d:%04.1f", sign, d, m, s); + else + sprintf (str, "%02d:%02d:%04.1f", d, m, s); + + return (str); +} + + +char * +toSexaTime (int nsec) +{ + char tstr[SZ_LINE]; + int m, s; + + m = nsec / 60; + s = nsec % 60; + + sprintf (tstr, "%02d:%02d", m, s); + + return (strdup (tstr)); /* note potential memory leak! */ +} + + +char * +vot_mktemp (char *root) +{ + char *tmp; + static char tmpfile[SZ_LINE]; + char *tmpdir = "/tmp"; + + + /* Get a temporary file name based on the pid. + */ + bzero (tmpfile, SZ_LINE); + if ((tmp = getenv ("TMP")) != NULL) + tmpdir = tmp; + sprintf (tmpfile, "%s/%s%d", tmpdir, root, (int)(getpid()+time((time_t)0))); + + return (tmpfile); +} + + +/* Copy the standard input to a temp file we can parse more easily. +*/ +char * +vot_copyStdin () +{ + static char *line, tmpfile[SZ_FNAME]; + FILE *fd; + extern char *vot_getline(); + + + /* Open a temp file and copy the stdin to it. + */ + strcpy (tmpfile, vot_mktemp ("vodo")); + if ((fd = fopen (tmpfile, "w+")) == (FILE *) NULL) { + fprintf (stderr, "Error opening tmp file '%s'\n", tmpfile); + return ((char *)NULL); + } + + while ( (line = vot_getline (stdin)) ) + fprintf (fd, "%s\n", line); + fclose (fd); + + return (tmpfile); +} + + +/* Skip header lines of a table. +*/ +void +vot_skipHdr (FILE *fd) +{ + register int i; + char line[SZ_LINE]; + + + if (fd && table_hskip) { /* Skip header lines */ + rewind (fd); + for (i=0; i < table_hskip; i++) { + if (fgets (line, SZ_LINE, fd) == NULL) { + break; + } + } + } +} + + + +/**************************************************************************** +** GETTABLECOL -- Get the requested column value from the table line. +** Column numbers are assumed to be one-indexed. +*/ +char * +vot_getTableCol (char *line, int col, int span) +{ + int i, nsp = span; + char sep[6], *ip, *op, *del = (char *)NULL; + static char value[SZ_LINE]; + + + bzero (value, SZ_LINE); + bzero (sep, 6); + + /* If we're doing exact columns, copy whatever is in those columns + ** to the output file. Otherwise, parse the line based on delimiters. + */ + if (ecols) { + strncpy (value, (char *)&line[col-1], span); + for (i=span-1; i && isspace(value[i]); i--) /* trailing space */ + value[i] = '\0'; + for (i=0; isspace(value[i]); i++) /* leading space */ + ; + return (&value[i]); + } + + if ((del = strpbrk(line, " \t,|;"))) /* get delimiter */ + sep[0] = del[0]; + else + strcpy (sep, delim); + + op = value; + for (i=1, ip=line; *ip; ip++) { + if (strchr (sep, (int)*ip) || *ip == '\n') { + if (sep[0] == ' ') { + while ( *ip == sep[0] ) /* skip multiple spaces */ + ip++; + if (*ip != '\n') + ip--; /* reposition for next */ + } + if (i++ == col) { + if (--nsp == 0) { + return (value); + } else { + *op++ = ' '; /* add a space for span */ + i--; + } + } else + bzero ((op=value), SZ_LINE); + } else + *op++ = *ip; + } + + return ( (i == col) ? value : (char *)NULL ); +} + + +/** + * VOT_ISNUMERICFIELD -- Determine if a <FIELD> is a numeric datatype. + */ +int +vot_isNumericField (handle_t field) +{ + char *dtype = vot_getAttr (field, "datatype"); + char *asize = vot_getAttr (field, "arraysize"); + + + if (asize && asize[0]) { + return (0); + + } else { + if ((strncasecmp (dtype, "floatComplex", 12) == 0) || + (strncasecmp (dtype, "doubleComplex", 13) == 0)) + return (0); + + if ((strncasecmp (dtype, "short", 5) == 0) || + (strncasecmp (dtype, "int", 3) == 0) || + (strncasecmp (dtype, "long", 4) == 0) || + (strncasecmp (dtype, "float", 5) == 0) || + (strncasecmp (dtype, "double", 6) == 0)) + return (1); + } + return (0); +} + + +/** + * VOT_FILETYPE -- Determine what type of file we have. + */ +int +vot_fileType (char *fname) +{ + FILE *fd = (FILE *) NULL; + char buf[1024]; + int nread, ftype = -1; + + if ((fd = fopen (fname, "r")) != NULL) { + memset (buf, 0, 1024); + nread = fread (buf, 1023, 1, fd); + if (strncasecmp ("SIMPLE", buf, 6) == 0) { + /* FIXME -- Need to add spectrum serialization. */ + ftype = VOT_FITS; + } else if (strcasestr (buf, "VOTABLE")) { + /* FIXME -- Need to add spectrum serialization. */ + ftype = VOT_VOTABLE; + } + fclose (fd); + } else + fprintf (stderr, "fileType: cannot open '%s'\n", fname); + + return (ftype); +} + + +/** + * VOT_SUM32 -- Internet checksum, 32 bit unsigned integer version. + */ +int +vot_sum32 (char *str) +{ + register int i; + unsigned int *iarray; + unsigned long lsum = 0; + int sum = 0; + int len, carry=0, newcarry=0; + + iarray = (unsigned int *) str; + len = strlen (str) / 4; + + for (i=0; i<len; i++) { + if (iarray[i] > ~ lsum) + carry++; + lsum += iarray[i]; + } + + while (carry) { + if (carry > ~ lsum) + newcarry++; + lsum += carry; + carry = newcarry; + newcarry = 0; + } + + return (abs(sum = lsum)); +} + + +/** + * STRDIC -- Search a dictionary string for a match with an input string. + * The input string may be an abbreviation of a dictionary entry, however, + * it is an error if the abbreviation is not unique. The entries in the + * dictionary string are separated by a delimiter character which is the + * first character of the dictionary string. The full name of the matched + * dictionary entry found is returned in out_str; the function value is + * the word index of the dictionary entry. The output string may be the + * same as the input string. + */ + +#include <ctype.h> + +int strdic ( + char *in_str, /* Input string, always lower case */ + char *out_str, /* Output string as found in dictionary */ + int maxchars, /* Maximum length of output string */ + char *dict /* Dictionary string */ +) +{ + char ch, fch; + int start, len, ip, i, match, entry; + + + if (dict == NULL || dict[0] == '\0') + return (0); + + for (i=0; isspace(in_str[i]); i++) + ; + + start = i; + match = -1; + ip = 1; + len = strlen (&in_str[start]); + fch = in_str[start]; + + + /* Search the dictionary string. If the input string matches a + * dictionary entry it is either an exact match (len = dictionary + * entry length) or a legal abbreviation. If an abbreviation + * matches two entries it is ambiguous and an error. + */ + for (entry=0; dict[ip] != '\0'; entry=entry+1) { + if (dict[ip] == fch) { + if (strncmp (&dict[ip], &in_str[start], len) == 0) { + for (i=0; i < maxchars; i++) { + ch = dict[ip+i-1]; + if ((ch == dict[0]) || (ch == '\0')) + break; + out_str[i] = ch; + } + out_str[i] = '\0'; + + if ((dict[ip+len] == dict[0]) || (dict[ip+len] == '\0')) + return (entry); /* exact match */ + else { + /* If we already have a match and the new match is not + * exact, then the abbreviation is ambiguous. + */ + if (match != 0) + return (0); + else + match = entry; + } + } + } + + do { + ip = ip + 1; + } while (dict[ip-1] != dict[0] && dict[ip] != '\0'); + } + + if (match <= 0) + strcpy (out_str, in_str); + return (match); +} + + +/***************************************************************************** +****** URL String Encode / Decode ****** +*****************************************************************************/ + +/* Converts a hex character to its integer value */ +static char from_hex (char ch) +{ + return (isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10); +} + +/* Converts an integer value to its hex character*/ +static char to_hex (char code) +{ + static char hex[] = "0123456789abcdef"; + return (hex[code & 15]); +} + + +/** + * VO_URLENCODE -- Returns a url-encoded version of str. Call must free() + * the pointer that is returned. + */ +char * +vo_urlEncode (char *str) +{ + char *pstr = str, *buf = malloc(strlen(str) * 3 + 1), *pbuf = buf; + + while (*pstr) { + if (isalnum(*pstr) || + *pstr == '-' || + *pstr == '_' || + *pstr == '.' || + *pstr == '~') + *pbuf++ = *pstr; + else if (*pstr == ' ') + *pbuf++ = '+'; + else { + *pbuf++ = '%'; + *pbuf++ = to_hex (*pstr >> 4); + *pbuf++ = to_hex (*pstr & 15); + } + pstr++; + } + *pbuf = '\0'; + return buf; +} + + +/** + * VO_URLDECODE -- Returns a url-decoded version of str. Call must free() + * the pointer that is returned. + */ +char * +vo_urlDecode (char *str) +{ + char *pstr = str, *buf = malloc(strlen(str) + 1), *pbuf = buf; + + while (*pstr) { + if (*pstr == '%') { + if (pstr[1] && pstr[2]) { + *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]); + pstr += 2; + } + } else if (*pstr == '+') { + *pbuf++ = ' '; + } else { + *pbuf++ = *pstr; + } + pstr++; + } + *pbuf = '\0'; + + return buf; +} + + +/** + * VOT_TOURL -- Convert a filename to a URL. + */ +char * +vot_toURL (char *arg) +{ + /* If we have an existing protocol simply return the argument. + */ + if ((strncmp (arg, "http:", 5) == 0) || + (strncmp (arg, "file:", 5) == 0) || + (strncmp (arg, "ftp:", 4) == 0)) + return (arg); + + if (access (arg, F_OK) == 0) { + char cwd[SZ_LINE]; + static char buf[SZ_LINE]; + + memset (cwd, 0, SZ_LINE); + getcwd (cwd, (unsigned long) SZ_LINE); + + memset (buf, 0, SZ_LINE); + if (arg[0] == '/') + sprintf (buf, "file://%s", arg); + else + sprintf (buf, "file://%s/%s", cwd, arg); + + return (buf); + } + + return (arg); +} + + +/** + * VOT_ISVALIDFORMAT -- Check whether we have a supported format request. + */ +int +vot_isValidFormat (char *fmt) +{ + char format[SZ_LINE]; + extern int strdic (); + + return ( (strdic (fmt, format, SZ_FORMAT, FORMATS) >= 0) ); +} + + +/** + * VOT_ATOI -- System atoi() with lexical argument checking. + */ +int +vot_atoi (char *val) +{ + char *ip; + + for (ip = val; *ip; ip++) { + if (isalpha ((int) *ip)) { + fprintf (stderr, "Warning: value '%s' is not an integer\n", val); + break; + } + } + return (atoi (val)); +} + + +/** + * VOT_ATOL -- System atol() with lexical argument checking. + */ +long +vot_atol (char *val) +{ + char *ip; + + for (ip = val; *ip; ip++) { + if (isalpha ((int) *ip) && *ip != '-' && *ip != '+') { + fprintf (stderr, "Warning: value '%s' is not an integer\n", val); + break; + } + } + return (atol (val)); +} + + +/** + * VOT_ATOF -- System atoi() with lexical argument checking. + */ +double +vot_atof (char *val) +{ + char *ip, c; + + for (ip = val; *ip; ip++) { + c = *ip; + if (! (tolower(c) == 'e' || tolower(c) == 'd' || isspace(c) || + (c == '-' || c == '+' || c == '.') || isdigit(c))) { + fprintf (stderr, + "Warning: value '%s' is not a floating point value\n", val); + break; + } + } + return (atof (val)); +} diff --git a/vendor/voclient/voapps/lib/voXML.c b/vendor/voclient/voapps/lib/voXML.c new file mode 100644 index 00000000..dbe01ff6 --- /dev/null +++ b/vendor/voclient/voapps/lib/voXML.c @@ -0,0 +1,166 @@ +/************************************************************************ +** VOXML.C -- Utility procedures for writing XML files, i.e. the raw +** VOTable output wrapped in a proprietary XML document. +** +** M. Fitzpatrick, NOAO, July 2007 +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/ipc.h> +#include <sys/sem.h> +#include <string.h> +#include <math.h> +#include "VOClient.h" +#include "voAppsP.h" + +extern int format, debug, errno, extract; +extern char *output; + +extern Service *svcList; +extern Object *objList; + +extern char *vot_getSName (char *root); +extern char *vot_getOName (char *root); +extern char *vot_procTimestamp (void); + +void vot_concatXML (char *fname); +int vot_copyXMLFile (char *root, char *sname, FILE *fd); +void vot_cleanXML (void); + + +/************************************************************************ +** CONCATXML -- Concatenate the XML file generated by the query into a +** single, hierarchical document grouped by the service. +*/ +void +vot_concatXML (char *fname) +{ + FILE *fd = (FILE *) NULL; + Service *svc = svcList; /* the service list */ + Proc *proc; /* process list in each service */ + int index = 0; + char sname[SZ_LINE], oname[SZ_LINE]; + + + if (fname[0] == '-') + fd = stdout; + else if ((fd = fopen (fname, "w+")) == (FILE *) NULL) { + fprintf (stderr, "ERROR: Cannot open XML file: '%s'\n", fname); + return; + } + + fprintf (fd, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); + fprintf (fd, "<VOTABLES date=\"%s\">\n", vot_procTimestamp()); + + for (svc=svcList; svc; svc=svc->next) { + + bzero (sname, SZ_FNAME); + strcpy (sname, vot_getSName (svc->proc->root)); + + for (proc=svc->proc; proc; proc=proc->next) { + + bzero (oname, SZ_FNAME); + strcpy (oname, vot_getOName (proc->root)); + + fprintf (fd, "<VOTABLE_ENTRY index=\"%d\"", index); + fprintf (fd, " svc=\"%s\" ", + (strcmp ("tmp",sname) == 0 ? svc->name : sname)); + if (!oname[0]) { + fprintf (fd, "pos=\"(%f,%f)\" ", + proc->obj->ra, proc->obj->dec); + } + fprintf (fd, "obj=\"%s\">\n", oname); + + vot_copyXMLFile (proc->root, oname, fd); + + fprintf (fd, "\n</VOTABLE_ENTRY>\n"); + index++; + } + } + + fprintf (fd, "</VOTABLES>\n"); + + /* Clean up the intermediate files if needed. + if (format & F_XML || (extract & EX_XML && extract & EX_COLLECT)) + */ + if (format & F_XML && (extract & EX_COLLECT)) + vot_cleanXML (); + + /* Close the file descriptors. + */ + if (fd != stdout) + fclose (fd); +} + + +/************************************************************************ +** COPYXMLFILE -- Copy a VOTable to the output XML file. +*/ +int +vot_copyXMLFile (char *root, char *name, FILE *fd) +{ + char *ip, line[4096], fname[SZ_FNAME]; + FILE *ifd; + extern char *strcasestr(); + + + bzero (fname, SZ_FNAME); + sprintf (fname, "%s.xml", root); + + if (access (fname, R_OK) == 0) { + if ((ifd = fopen (fname, "r")) == (FILE *) NULL) { + fprintf (stderr, "Warning: Cannot open file '%s'\n", fname); + return (ERR); + } + } else { + return (OK); + } + + /* Skip ahead to the start of the part we're interested in. + */ + bzero (line, 4096); + while (fgets (line, 4096, ifd)) { + if ((ip = strcasestr (line, "<VOTABLE"))) { + fprintf (fd, "%s", ip); + break; + } + bzero (line, 4096); + } + + /* (Slow) Copy the file until the end of the Document. + */ + bzero (line, 4096); + while (fgets (line, 4096, ifd)) { + if (strcasestr (line, "</VOTABLE>")) { + fprintf (fd, "%s", line); + break; + } + fprintf (fd, " %s", line); + bzero (line, 4096); + } + + fclose (ifd); + return (OK); +} + + +/************************************************************************ +** CLEANXML -- Clean up the intermediate VOTable files when producing +** the compiled XML doc.. +*/ +void +vot_cleanXML () +{ + Service *svc = svcList; /* the service list */ + Proc *proc; /* process list in each service */ + char fname[SZ_FNAME]; + + for (svc=svcList; svc; svc=svc->next) { + for (proc=svc->proc; proc; proc=proc->next) { + bzero (fname, SZ_FNAME); + sprintf (fname, "%s.vot", proc->root); + unlink (fname); + } + } +} diff --git a/vendor/voclient/voapps/lib/vosUtil.c b/vendor/voclient/voapps/lib/vosUtil.c new file mode 100644 index 00000000..732daf45 --- /dev/null +++ b/vendor/voclient/voapps/lib/vosUtil.c @@ -0,0 +1,998 @@ +/** + * VOSUTIL - Utility routines for the VOSAMP tools. + * + * @file vosUtil.c + * @author Mike Fitzpatrick + * @date 6/03/11 + * + * @brief Utility routines for the VOSAMP tools. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <fcntl.h> +#include <time.h> + +#include <netdb.h> +#include <sys/errno.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <curl/curl.h> +#include <curl/types.h> +#include <curl/easy.h> + + +#include "samp.h" /* LIBSAMP interface */ +#include "voApps.h" /* voApps interface */ + + +#define SZ_MTYPE 64 +#define SZ_BUF 128 +#define SZ_HOSTIP 16 +#define SZ_APPNAME 16 + +#define VOS_DEBUG (getenv("VOS_DBG")!=NULL||access("/tmp/VOS_DBG",F_OK)==0) + + +typedef struct { + int nbytes; /* length of msg body */ + int mode; /* sync, async, notify */ + int type; /* SAMP cmd, data, result */ + char fname[SZ_FNAME]; /* upload data name */ + int fsize; /* data file size */ + char session[SZ_APPNAME]; /* session name */ + int sessionPort; /* session port number */ + char recipient[SZ_APPNAME]; /* recipient app name */ + char senderIP[SZ_HOSTIP]; /* sender's IP address */ + int senderPort; /* sender's port */ + + int verbose; /* verbose flag */ + int debug; /* debug flag */ +} cmdHdr, *cmdHdrP; + +cmdHdr msgHdr; + + +extern char *to, senderIP[SZ_HOSTIP]; + + +char *vos_toURL (char *arg); +char *vos_optArg (char *arg); +char *vos_getLocalIP (void); +char *vos_getFName (char *path); +char *vos_typeName (int type); + +int *vos_toIntArray (char *arg, int *nrows); +int vos_urlType (char *url); +int vos_getURL (char *url, char *fname); + + + +/* Private socket routines. + */ +int vos_openServerSocket (int port); +int vos_openClientSocket (char *host, int port, int retry); +int vos_sockRead (int fd, void *vptr, int nbytes); +int vos_sockWrite (int fd, void *vptr, int nbytes); +void vos_setNonBlock (int sock); +int vos_sockWriteHdr (int fd, int len, char *name, int type, int mode, + char *to); +int vos_sockReadHdr (int fd, int *len, char *name, int *type, int *mode); +void vos_sockPrintHdr (char *msg, int fd); +struct hostent *vos_getHostByName (char *lhost); +struct hostent *vos_dupHostent (struct hostent *hentry); + + + + +/**************************************************************************** + */ + + +/** + * VOS_URLTYPE -- Determine the type of a URL parameter + */ +int +vos_urlType (char *url) +{ + if (strncasecmp (url, "http://127.0.0.1", 16) == 0) + return (VOS_LOCALURL); + else if (strncasecmp (url, "file://", 7) == 0) + return (VOS_LOCALURI); + else if (strncasecmp (url, "http://", 7) == 0) + return (VOS_REMOTE); + else if (access (url, F_OK) == 0) + return (VOS_LOCALFILE); + + return (-1); +} + + +/** + * VOS_GETFNAME -- Get a filename from a path or URL. + */ +char * +vos_getFName (char *path) +{ + static char fname[SZ_FNAME]; + static int filenum = 0; + + memset (fname, 0, SZ_FNAME); + if (access (path, R_OK) == 0) { + int i, len = strlen (path); + + for (i=len-1; i >=0 && path[i] != '/'; i--) ; /* get filename */ + strcpy (fname, &path[i+1]); + } + + if (!fname[0]) + sprintf (fname, "vos%d_%03d", (int)getpid(), filenum++); + + return (fname); +} + + +/** + * VOS_TYPENAME -- Convert a message type code to a string. + */ +char * +vos_typeName (int type) +{ + switch (type) { + case SAMP_DATA: return ("SAMP_DATA"); + case SAMP_CMD: return ("SAMP_CMD"); + case SAMP_RELAY: return ("SAMP_RELAY"); + case SAMP_TEST: return ("SAMP_TEST"); + case SAMP_QUIT: return ("SAMP_QUIT"); + default: return ("unknown"); + } +} + + +/** + * VOS_GETURL -- Utility routine to do a simple URL download to the file. + */ +int +vos_getURL (char *url, char *fname) +{ + int stat = 0; + char errBuf[SZ_LINE]; + FILE *fd; + CURL *curl_handle; + + + if (access (fname, F_OK) == 0) /* see if file already exists */ + unlink (fname); + + + /* For the CURL operation to download the file. + */ + curl_global_init (CURL_GLOBAL_ALL); /* init curl session */ + curl_handle = curl_easy_init (); + + /* Open the output file. + */ + if ((fd = fopen (fname, "wb")) == NULL) { + fprintf (stderr, "Error: cannot open output file '%s'\n", fname); + curl_easy_cleanup (curl_handle); + return -1; + } + + /* Set cURL options + */ + curl_easy_setopt (curl_handle, CURLOPT_URL, url); + curl_easy_setopt (curl_handle, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt (curl_handle, CURLOPT_WRITEDATA, fd); + curl_easy_setopt (curl_handle, CURLOPT_ERRORBUFFER, errBuf); + curl_easy_setopt (curl_handle, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt (curl_handle, CURLOPT_FAILONERROR, 1); + + /* Do the download. + */ + if ((stat = curl_easy_perform (curl_handle)) != 0) { + /* Error in download, clean up. + */ + fprintf (stderr, "Error: can't download '%s' : %s\n", url, errBuf); + unlink (fname); + fclose (fd); /* close the file */ + curl_easy_cleanup (curl_handle); /* cleanup curl stuff */ + return (-1); + } + + fflush (fd); + fclose (fd); /* close the file */ + curl_easy_cleanup (curl_handle); /* cleanup curl stuff */ + + return (1); +} + + +/** + * VOS_OPTARG -- Input command arguments are allowed to be of the form + * 'param=value', but the SAMP interface only wants the value string. + * Skip past the '=' and return the value, or just return the value if + * there is no parameter name. + */ +char * +vos_optArg (char *arg) +{ + char *ip, first = (arg ? *arg : 0); + + if (!arg || !first) return (""); + return ( ((ip = strchr (arg, (int) '=')) ? ++ip : arg) ); +} + + +/** + * VOS_TOURL -- Convert the argument to a URL suitable for a message. + */ +char * +vos_toURL (char *arg) +{ + /* If we have an existing protocol simply return the argument. + */ + if ((strncmp (arg, "http:", 5) == 0) || + (strncmp (arg, "file:", 5) == 0) || + (strncmp (arg, "ftp:", 4) == 0)) + return (arg); + + if (access (arg, F_OK) == 0) { + static char buf[SZ_FNAME]; + + memset (buf, 0, SZ_FNAME); + if (arg[0] != '/') { + char cwd[SZ_FNAME]; + + memset (cwd, 0, SZ_FNAME); + getcwd (cwd, (unsigned long) SZ_FNAME); + sprintf (buf, "file://%s/%s", cwd, arg); + } else + sprintf (buf, "file://%s", arg); + + return (buf); + } + + return (arg); +} + + +/** + * VOS_TOINTARRAY -- Convert a range string to an unpacked array of ints. + */ +#define MAX_RANGES 256 +#define SZ_ROW 16 + +int * +vos_toIntArray (char *arg, int *nrows) +{ + int i, val, nvalues; + static int ranges[MAX_RANGES], values[MAX_ROWS]; + extern int vot_decodeRanges(), get_next_number(); + + + memset (values, 0, (sizeof(int) * MAX_ROWS)); + memset (ranges, 0, (sizeof(int) * MAX_RANGES)); + + if (vot_decodeRanges (arg, ranges, MAX_RANGES, &nvalues) < 0) + fprintf (stderr, "Error decoding range string.\n"); + + for (i=0, val=0; (val = get_next_number (ranges, val)) > 0; i++ ) + values[i] = val; + + *nrows = nvalues; + return (values); +} + + + +/***************************************************************************** +**** Socket Utilities +*****************************************************************************/ + + +#define SELWIDTH 32 +#define SOCK_MAX_TRY 3 + +/** + * VOS_OPENSERVERSOCKET -- Open a socket to be used on the 'server' side. + * + * @brief Open a socket to be used on the 'server' side + * @fn int vos_openServerSocket (int port) + * + * @param port port number to open + * @return socket descriptor + * + */ +int +vos_openServerSocket (int port) +{ + struct sockaddr_in servaddr; /* server address */ + int ps = 0; /* parallel socket descriptor */ + int32_t yes = 1, ntries = 5; + + + /* Create a socket. + */ + if ((ps = socket (AF_INET, SOCK_STREAM, 0)) < 0) { + fprintf (stderr, "openServerSocket(%d): %s\n", port, strerror(errno)); + return (-1); + } + setsockopt (ps, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)); + + if (VOS_DEBUG) + fprintf (stderr, "server socket %d on %s:%d\n", ps, + vos_getLocalIP(), port ); + + + /* Set server address. + */ + memset (&servaddr, 0, sizeof servaddr); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(port); + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + + /* Bind to the server socket and listen for a connection. + */ + while (ntries--) { + if (bind (ps, (struct sockaddr*)&servaddr, sizeof servaddr) < 0) { + if (!ntries) + return (-1); + } else { + if ((listen (ps, SOMAXCONN)) < 0) { + fprintf (stderr, + "serverSock: listen(%d:%s)", port, strerror(errno)); + if (!ntries) + return (-1); + } else { + break; + } + } + sleep (1); + } + + return (ps); +} + + +/** + * VOS_OPENCLIENTSOCKET -- Open a socket to be used on the 'client' side. + * + * @brief Open a socket to be used on the 'client' side + * @fn int vos_openClientSocket (char *host, int port, int retry) + * + * @param host host name + * @param port port number to open + * @param retry attempt to reconnect? + * @return socket descriptor + * + */ +int +vos_openClientSocket (char *host, int port, int retry) +{ + char *ip, lhost[SZ_LINE]; + struct sockaddr_in servaddr; /* server address */ + int ps = 0; /* parallel socket descriptor */ + socklen_t ctry = 0, yes = 1; + + + /* Remove any server port information from the host specification. + */ + memset (lhost, 0, SZ_LINE); + strcpy (lhost, host); + if ( (ip = strchr (lhost, (int) ':')) ) + *ip = '\0'; + + /* Create a socket. + */ + if ((ps = socket (AF_INET, SOCK_STREAM, 0)) < 0) { + fprintf (stderr, "openClientSocket(%s:%d): %s\n", + host, port, strerror(errno)); + return (-1); + } + setsockopt (ps, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)); + + + /* Set server address. + */ + memset (&servaddr, 0, sizeof (struct sockaddr_in)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(port); + + /* Connect to server. + */ + for (ctry = (retry ? 0 : SOCK_MAX_TRY); ctry <= SOCK_MAX_TRY; ctry++) { + + if ( !inet_aton(lhost, &servaddr.sin_addr) ) { + struct hostent *he = vos_getHostByName ( lhost ); + + if (!he) { + fprintf (stderr, "Cannot resolve address.\n"); + exit (2); + } + if (he->h_addrtype != AF_INET || + he->h_length != sizeof (servaddr.sin_addr)) { + fprintf (stderr, "Cannot handle addr type %d, length %d.\n", + he->h_addrtype, he->h_length); + exit(2); + } + memcpy (&servaddr.sin_addr, he->h_addr_list[0], + sizeof (servaddr.sin_addr) ); + } + + if (connect (ps, (struct sockaddr *)&servaddr, sizeof servaddr) < 0) { + if (!retry || ctry == SOCK_MAX_TRY) { + fprintf (stderr, + "client connect() failed to %s:%d, try %d, retry %d\n", + lhost, port, ctry, retry); + close (ps); + ps = -1; + break; + } else + sleep (1); + } else + break; + } + + return (ps); +} + + +/** + * VOS_TESTCLIENTSOCKET -- Test a socket to be used on the 'client' side. + * + * @brief Test a socket to be used on the 'client' side + * @fn int vos_testClientSocket (char *host, int port) + * + * @param host host name + * @param port port number to open + * @return socket descriptor or -1 if connect fails + * + */ +int +vos_testClientSocket (char *host, int port) +{ + char *ip, lhost[SZ_LINE]; + struct sockaddr_in servaddr; /* server address */ + int sock = 0; /* socket descriptor */ + socklen_t yes = 1; + + + /* Remove any server port information from the host specification. + */ + memset (lhost, 0, SZ_LINE); + strcpy (lhost, host); + if ( (ip = strchr (lhost, (int) ':')) ) + *ip = '\0'; + + /* Create a socket. + */ + if ((sock = socket (AF_INET, SOCK_STREAM, 0)) < 0) + return (-1); + setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)); + + + /* Set server address. + */ + memset (&servaddr, 0, sizeof (struct sockaddr_in)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(port); + + /* Connect to server. + */ + if ( !inet_aton(lhost, &servaddr.sin_addr) ) { + struct hostent *he = vos_getHostByName ( lhost ); + + if (!he) + return (-1); + if (he->h_addrtype != AF_INET || + he->h_length != sizeof (servaddr.sin_addr)) { + return (-1); + } + memcpy (&servaddr.sin_addr, he->h_addr_list[0], + sizeof (servaddr.sin_addr) ); + } + + if (connect (sock, (struct sockaddr *)&servaddr, sizeof servaddr) < 0) { + close (sock); + sock = -1; + } + return (sock); +} + + +/** + * VOS_SOCKWRITEHDR -- Write the socket message header. + */ +int +vos_sockReadHdr (int fd, int *len, char *name, int *type, int *mode) +{ + int nread = 0; + + memset (&msgHdr, 0, sizeof (msgHdr)); + if ((nread = vos_sockRead (fd, &msgHdr, sizeof (msgHdr))) > 0) { + *len = msgHdr.nbytes; + *type = msgHdr.type; + *mode = msgHdr.mode; + to = strdup (msgHdr.recipient); + strcpy (senderIP, msgHdr.senderIP); + if (name) + strcpy (name, msgHdr.fname); /* must be at least SZ_FNAME */ + } + + if (VOS_DEBUG) + vos_sockPrintHdr ("Read Hdr", fd); + + return (nread); +} + + +/** + * VOS_SOCKWRITEHDR -- Write the socket message header. + */ +int +vos_sockWriteHdr (int fd, int len, char *name, int type, int mode, char *to) +{ + int nwrite = 0; + + memset (&msgHdr, 0, sizeof (msgHdr)); + msgHdr.nbytes = len; + msgHdr.type = type; + msgHdr.mode = mode; + if (name && name[0]) { + struct stat st; + stat (name, &st); + strcpy (msgHdr.fname, name); + msgHdr.fsize = st.st_size; + } + strcpy (msgHdr.recipient, (to ? to : "all")); + strcpy (msgHdr.senderIP, vos_getLocalIP()); + + if (VOS_DEBUG) + vos_sockPrintHdr ("Write Hdr", fd); + + return ((nwrite = vos_sockWrite (fd, &msgHdr, sizeof(msgHdr)))); +} + + +/** + * VOS_SOCKPRINTHDR -- Debug utility to print a message header. + */ +void +vos_sockPrintHdr (char *msg, int fd) +{ + fprintf (stderr, "%s: fd=%d\n", msg, fd); + fprintf (stderr, " { 'type' : %d, 'mode' : %d,\n", + msgHdr.type, msgHdr.mode); + fprintf (stderr, " 'fname' : '%s', 'nbytes' : %d, 'fsize' : %d,\n", + msgHdr.fname, msgHdr.nbytes, msgHdr.fsize); + fprintf (stderr, " 'session' : '%s', 'port' : %d,\n", + msgHdr.session, msgHdr.sessionPort); + fprintf (stderr, " 'sender' : '%s', 'port' : %d, 'to' : '%s'\n", + msgHdr.senderIP, msgHdr.senderPort, msgHdr.recipient); + fprintf (stderr, " }\n"); +} + + +/** + * VOS_SOCKREAD -- Read exactly "n" bytes from a socket descriptor. + * + * @brief Recv exactly "n" bytes from a socket descriptor. + * @fn int vos_sockRead (int fd, void *vptr, int nbytes) + * + * @param fd file descriptor + * @param vptr data buffer to be written + * @param nbytes number of bytes to write + * @return number of bytes written + */ +int +vos_sockRead (int fd, void *vptr, int nbytes) +{ + char *ptr = vptr; + int nread = 0, nleft = nbytes, nb = 0; + fd_set allset, fds; + + + /* Set non-blocking mode on the descriptor. + */ + vos_setNonBlock (fd); + + FD_ZERO (&allset); + FD_SET (fd, &allset); + + while (nleft > 0) { + fds = allset; + if (select (SELWIDTH, &fds, NULL, NULL, NULL)) { + if ( (nb = recv (fd, ptr, nleft, 0)) < 0) { + if (errno == EINTR || errno == EAGAIN) + nb = 0; /* and call recv() again */ + else { + fprintf (stderr, "[%d] vos_sockRead:[%d] %s\n", + (int) getpid(), fd, strerror(errno)); + return (-1); + } + } else if (nb == 0) + break; /* EOF */ + nleft -= nb; + ptr += nb; + nread += nb; + } + } + + if (VOS_DEBUG) + fprintf (stderr, "sockRead: %d bytes on fd=%d\n", nread, fd); + + return (nread); /* return no. of bytes read */ +} + + +/** + * VOS_SOCKWRITE -- Write exactly "n" bytes to a socket descriptor. + * + * @brief Send exactly "n" bytes to a socket descriptor. + * @fn int vos_sockWrite (int fd, void *vptr, int nbytes) + * + * @param fd file descriptor + * @param vptr data buffer to be written + * @param nbytes number of bytes to write + * @return number of bytes written + */ +int +vos_sockWrite (int fd, void *vptr, int nbytes) +{ + char *ptr = vptr; + int nwritten = 0, nleft = nbytes, nb = 0; + fd_set allset, fds; + + + /* Set non-blocking mode on the descriptor. + */ + vos_setNonBlock (fd); + + FD_ZERO (&allset); + FD_SET (fd, &allset); + + while (nleft > 0) { + fds = allset; + if (select (SELWIDTH, NULL, &fds, NULL, NULL)) { + if ( (nb = send (fd, ptr, nleft, 0)) <= 0) { + if (errno == EINTR || errno == EAGAIN) + nb = 0; /* and call send() again */ + else { + /* + fprintf (stderr, "[%d] vos_sockWrite[%d]: %s\n", + (int) getpid(), fd, strerror (errno)); + */ + return (-1); + } + } + nleft -= nb; + ptr += nb; + nwritten += nb; + } + } + + if (VOS_DEBUG) + fprintf (stderr, "sockWrite: %d bytes on fd=%d\n", nwritten, fd); + + return (nwritten); +} + + +/** + * VOS_FILEREAD -- Read exactly "n" bytes from a socket descriptor. + * + * @brief Recv exactly "n" bytes from a socket descriptor. + * @fn int vos_sockRead (int fd, void *vptr, int nbytes) + * + * @param fd file descriptor + * @param vptr data buffer to be written + * @param nbytes number of bytes to write + * @return number of bytes written + */ +int +vos_fileRead (int fd, void *vptr, int nbytes) +{ + char *ptr = vptr; + int nread = 0, nleft = nbytes, nb = 0; + + while (nleft > 0) { + if ( (nb = read(fd, ptr, nleft)) < 0) { + if (errno == EINTR) + nb = 0; /* and call read() again */ + else + return(-1); + } else if (nb == 0) + break; /* EOF */ + nleft -= nb; + ptr += nb; + nread += nb; + } + return (nread); /* return no. of bytes read */ +} + + +/** + * VOS_FILEWRITE -- Write exactly "n" bytes to a file descriptor. + * + * @brief Send exactly "n" bytes to a file descriptor. + * @fn int vos_fileWrite (int fd, void *vptr, int nbytes) + * + * @param fd file descriptor + * @param vptr data buffer to be written + * @param nbytes number of bytes to write + * @return number of bytes written + */ +int +vos_fileWrite (int fd, void *vptr, int nbytes) +{ + char *ptr = vptr; + int nwritten = 0, nleft = nbytes, nb = 0; + + while (nleft > 0) { + if ( (nb = write(fd, ptr, nleft)) <= 0) { + if (errno == EINTR) + nb = 0; /* and call write() again */ + else + return(-1); /* error */ + } + nleft -= nb; + ptr += nb; + nwritten += nb; + } + return (nwritten); +} + + +/** + * VOS_SETNONBLOCK -- Set a non-blocking mode on the socket descriptor. + */ +void +vos_setNonBlock (int sock) +{ + int flags; + + + /* Set socket to non-blocking. + */ + if ((flags = fcntl (sock, F_GETFL, 0)) < 0) { + /* Handle error */ + return; + } + if (fcntl (sock, F_SETFL, flags | O_NONBLOCK) < 0) { + /* Handle error */ + return; + } +} + + +/** + * VOS_GETLOCALIP -- Get the IP address of the local machine. + */ +char * +vos_getLocalIP (void) +{ + const char *kGoogleDnsIp = "8.8.8.8"; /* Google's public DNS server */ + unsigned short kDnsPort = 53; + struct sockaddr_in serv; + int sock, err; + const char *p; + char buffer[SZ_BUF]; + static int initialized = 0; + static char localIP[SZ_BUF]; + + + /* Only get the IP once, afterwards just return the value. + */ + if (initialized++) + return (localIP); + + memset (buffer, 0, SZ_BUF); + memset (localIP, 0, SZ_BUF); + + if ((sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0) + return ("127.0.0.1"); /* cannot get socket, punt */ + + memset (&serv, 0, sizeof (serv)); + serv.sin_family = AF_INET; + serv.sin_addr.s_addr = inet_addr(kGoogleDnsIp); + serv.sin_port = htons(kDnsPort); + + if ((err = connect(sock, (struct sockaddr*)&serv, sizeof(serv))) >= 0) { + struct sockaddr_in name; + socklen_t namelen = sizeof(name); + + if ((err=getsockname(sock, (struct sockaddr*)&name, &namelen)) < 0) + strcpy (buffer, "127.0.0.1"); /* cannot connect socket */ + else + if ((p=inet_ntop(AF_INET, &name.sin_addr, buffer, SZ_BUF)) == NULL) + strcpy (buffer, "127.0.0.1"); /* cannot get IP buffer name */ + } else + strcpy (buffer, "127.0.0.1"); /* cannot get IP buffer name */ + + if (strncmp (buffer, "192.168.", 8) == 0) + strcpy (buffer, "127.0.0.1"); /* cannot get IP buffer name */ + + close(sock); + + strcpy (localIP, buffer); + return (localIP); +} + + +/** + * VOS_GETHOSTBYNAME -- Get the host entry associated with a (cached) name. + * + * @fn char *vos_getHostByName (char *name) + * + * @param name host name + * @return host entry structure pointer + */ +typedef struct { + char name[SZ_LINE]; + char ip[SZ_LINE]; + struct hostent *host; +} hostTab, *hostTabP; + +struct hostent_wrapper { + struct hostent hentry; + int status; +}; + +static hostTab hostab[MAX_CLIENTS]; + + +struct hostent * +vos_getHostByName (char *name) +{ + static int initialized = 0; + struct in_addr x_addr; + struct hostent *hp = (struct hostent *) NULL; + hostTab *h = (hostTabP) hostab; + int i, len; + + + if (!initialized) { + memset (hostab, 0, sizeof (hostab)); + initialized++; + } + + for (i=0; i < MAX_CLIENTS; i++, h++) { + if (h && h->name[0]) { + len = min (strlen (name), strlen (h->name)); + if (strncmp (name, h->name, len) == 0) + return (h->host); + } else + break; /* end of cache list */ + } + + /* If we overflow the cache use a DNS lookup. + */ + if (i >= MAX_CLIENTS) { + fprintf (stderr, "vos_getHostByName(): cache overflow on '%s'", name); + hp = gethostbyname (name); + return (hp); + } + + /* Host not found, resolve and add it to the cache. + */ + hp = gethostbyname (name); + if (hp == (struct hostent *) NULL) { + fprintf (stderr, "vos_getHostByName: cannot resolve '%s'\n", name); + exit (0); + } + + strcpy (h->name, name); + x_addr.s_addr = *((unsigned long *) hp->h_addr_list[0]); + strcpy (h->ip, inet_ntoa (x_addr)); + + h->host = vos_dupHostent (hp); + return (h->host); +} + + +/** + * VOS_DUPHOSTENT -- Duplicate a hostent structure via a deep copy. + */ +struct hostent * +vos_dupHostent (struct hostent *hentry) +{ + struct hostent_wrapper *oldhw = NULL; + struct hostent_wrapper *newhw = NULL; + int i = 0; + int aliascount=0; + int addrcount=0; + + + if (!hentry) + return NULL; + + oldhw = (struct hostent_wrapper *) hentry; + newhw = (struct hostent_wrapper *) malloc (sizeof (struct hostent_wrapper)); + bzero(newhw, sizeof (struct hostent_wrapper)); + + newhw->hentry.h_addrtype = hentry->h_addrtype; + newhw->hentry.h_length = hentry->h_length; + newhw->status = oldhw->status; + + if (hentry->h_name) + newhw->hentry.h_name = strdup(hentry->h_name); + + if (hentry->h_aliases) { + for (i=0; hentry->h_aliases[i] != 0; i++) + aliascount++; + aliascount++; + + newhw->hentry.h_aliases = (char **)malloc (aliascount * sizeof (char*)); + bzero(newhw->hentry.h_aliases, aliascount * sizeof(char*)); + + for (i=0; hentry->h_aliases[i] != 0; i++) { + if (hentry->h_aliases[i]) + newhw->hentry.h_aliases[i] = strdup (hentry->h_aliases[i]); + } + } + + if (hentry->h_addr_list) { + for (i=0; hentry->h_addr_list[i] != 0; i++) + addrcount++; + addrcount++; + + newhw->hentry.h_addr_list = + (char **) malloc (addrcount * sizeof (char *)); + bzero (newhw->hentry.h_addr_list, addrcount * sizeof (char *)); + + for (i=0; hentry->h_addr_list[i] != 0; i++) { + if (hentry->h_addr_list[i]) + newhw->hentry.h_addr_list[i] = strdup (hentry->h_addr_list[i]); + } + } + + return (struct hostent *) newhw; +} + +/** + * VOS_STRSUB -- Do a string subsitution. + */ +int +vos_strsub (char *in, char *from, char *to, char *outstr, int maxch) +{ + int flen = strlen (from); + int nsub = 0; + char *ip, *op; + + if (!from || !to) + return (0); + + for (ip=in, op=outstr; *ip; ip++) { + if (! *ip || (ip - in) > maxch) + break; + if (*ip == '$') { + /* Start of a macro. + */ + if (strncasecmp (ip, from, flen) == 0) { + /* Our macro, do the substitution. + */ + char *tp = to; + + ip += flen - 1; /* skip the input macro */ + while (*tp) /* copy replacement string */ + *op++ = *tp++; + nsub++; + } else { + /* Not our macro, just pass it through. + */ + *op++ = *ip; + } + } else { + *op++ = *ip; + } + } + *op = '\0'; + + return (nsub); +} diff --git a/vendor/voclient/voapps/session_cmd.c b/vendor/voclient/voapps/session_cmd.c new file mode 100644 index 00000000..41b70451 --- /dev/null +++ b/vendor/voclient/voapps/session_cmd.c @@ -0,0 +1,171 @@ +/** + * SESSION_CMD -- Session Manager test client. + * + * @file session_cmd.c + * @author Mike Fitzpatrick + * @date 6/03/12 + * + * @brief Session Manager test client. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <fcntl.h> +#include <time.h> + +#include <netdb.h> +#include <sys/errno.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "samp.h" /* SAMP interface */ +#include "voApps.h" /* voApps interface */ + + +#define SZ_BUF 1024 +#define SELWIDTH 4 + + +/* Utility socket routines. + */ +extern int vos_uploadFiles (int sock, char *cmd); +extern int vos_openClientSocket (char *host, int port, int retry); +extern int vos_sockRead (int fd, void *vptr, int nbytes); +extern int vos_sockWrite (int fd, void *vptr, int nbytes); +extern int vos_sockWriteHdr (int fd, int len, char *name, int type, + int mode, char *to); +extern int vos_sockReadHdr (int fd, int *len, char *name, int *type, + int *mode); + +extern int vos_openSession (char *host, int port, char *session_name); +extern int vos_closeSession (int sock); + +extern void vos_setNonBlock (int sock); +extern struct hostent *vos_getHostByName (char *lhost); + + + +/**************************************************************************** + * Program entry point. + */ +int +main (int argc, char **argv) +{ + int i, j, rc, debug=0, len=0, nw=0, cb_sock=0, nfiles=0; + int mgr_port = SESS_DEFPORT; + char *mgr_host = SESS_DEFHOST; + char *sname = "test"; + char buf[SZ_BUF]; + + fd_set allset, fds; + + + /* Process cmdline args. + */ + for (i=1; i < argc; i++) { + for (j=1; j < argc; j++) { + switch ( argv[i][j] ) { + case 'd': debug++; break; + + default: + fprintf (stderr, "Invalid option '%c'\n", argv[i][0]); + return (1); + } + } + } + + + + /* Open a client connection to the VOSAMP Session Manager. + */ + if ((cb_sock = vos_openSession (mgr_host, mgr_port, sname)) == 0) { + fprintf (stderr, "Cannot open connection to session manager\n"); + return (1); + } + + /* Take commands from the stdin, write results to stdout. + */ + printf ("vosession> "); fflush (stdout); + + FD_ZERO (&allset); + FD_SET (cb_sock, &allset); vos_setNonBlock (cb_sock); + FD_SET (fileno(stdin), &allset); vos_setNonBlock (fileno(stdin)); + + + /* Process input either from the stdin or the session manager. + */ + while (1) { + /* Initialize the input file descriptor set. + */ + memcpy (&fds, &allset, sizeof(allset)); + rc = select (SELWIDTH, &fds, NULL, NULL, NULL); + + for (i=0; i < SELWIDTH+1; i++) { + if (FD_ISSET(i, &fds)) { + if (i == fileno(stdin)) { + if (fgets (buf, SZ_BUF, stdin) == NULL) + goto done_; /* EOF, time to quit */ + buf[strlen(buf)-1] = '\0'; /* kill newline */ + + } else { + int nread, nbytes, type, mode; + char fname[SZ_FNAME]; + + if (vos_sockReadHdr (i, &nbytes, fname, &type, &mode)) + nread = vos_sockRead (i, buf, nbytes); + else + goto done_; + + switch (type) { + case SAMP_QUIT: + goto done_; + case SAMP_RESULT: + printf ("\r\n%s\n", buf); + goto next_cmd; + case SAMP_CMD: + printf ("Got cmd: '%s'\n", buf); + goto next_cmd; + case SAMP_TEST: + printf ("Got test cmd: '%s'\n", buf); + goto next_cmd; + case SAMP_RELAY: + printf ("Got relayed cmd: '%s'\n", buf); + goto next_cmd; + default: + printf ("Got msg type: %d\n", type); + goto next_cmd; + } + } + } + } + + /* If we want to quit, let the vos_closeSession() send the 'quit'. + */ + if (strncasecmp (buf, "quit", 4) == 0) + break; + + /* Upload any local files to the session manager. + */ + nfiles = vos_uploadFiles (cb_sock, buf); + if (debug) + if (nfiles) fprintf (stderr, "sent %d data files....\n", nfiles); + + /* Send the command string. + */ + len = strlen (buf); + if (vos_sockWriteHdr(cb_sock, len, NULL, SAMP_CMD, SAMP_NOTIFY, "smgr")) + nw = vos_sockWrite (cb_sock, buf, len); + +next_cmd: + memset (buf, 0, SZ_BUF); + printf ("vosession> "); fflush (stdout); + } + +done_: + vos_closeSession (cb_sock); + return (0); +} diff --git a/vendor/voclient/voapps/spp/README b/vendor/voclient/voapps/spp/README new file mode 100644 index 00000000..3b7a7688 --- /dev/null +++ b/vendor/voclient/voapps/spp/README @@ -0,0 +1,9 @@ + + This directory contains tasks written or designed for use with +IRAF SPP. In some cases these will simply be example tasks to exercise +or demonstrate the language support. + + +Current Tasks include: + + [None at this time] diff --git a/vendor/voclient/voapps/task/Makefile b/vendor/voclient/voapps/task/Makefile new file mode 100644 index 00000000..afd04b38 --- /dev/null +++ b/vendor/voclient/voapps/task/Makefile @@ -0,0 +1,169 @@ +#/////////////////////////////////////////////////////////////////////////////// +#// +#// Makefile for the VOClient Tasking Interface +#// +#/////////////////////////////////////////////////////////////////////////////// + +# primary dependencies + +NAME = voTask +VERSION = 1.0 +PLATFORM := $(shell uname -s) +PLMACH := $(shell uname -m) +HERE := $(shell /bin/pwd) +BINDIR := ../bin/ +LIBDIR := ../lib/ +INCDIR := ../include/ +PYVER := $(shell csh -c "python --version |& cut -c8-10") + +# secondary dependencies +LIBBASE = lib$(NAME) +STATICLIB = $(HERE)/$(LIBBASE).a +SHAREDLIB = $(HERE)/$(LIBBASE).so.$(VERSION) + + +# stuff that's precious to keep +.PRECIOUS: $(STATICLIB) $(SHAREDLIB) +.KEEP_STATE: + + +# includes, flags and libraries +CC = gcc +CINCS = -I$(INCDIR) -I. + +ifeq ($(PLATFORM),Darwin) + ifeq ($(PLMACH),x86_64) + CARCH = -m64 -mmacosx-version-min=10.5 + else + #CARCH = -arch i386 -arch ppc -m32 -mmacosx-version-min=10.4 + CARCH = -mmacosx-version-min=10.4 + endif + PYFLAGS = -dynamiclib -I/usr/include/python$(PYVER)/ -lpython$(PYVER) +else + CARCH = + PYFLAGS = -DLINUX +endif + +CLIBS = -lm -lc -lcurl -lpthread -lm +CFLAGS = -g -Wall $(CARCH) -D$(PLATFORM) $(CINCS) -L./ + + + +# includes, flags and libraries +CC = gcc +CINCS = -I$(HERE) -I../ -I../include -L../ -L../lib/ -L../ + +#F77 = g77 +F77 = gfortran +FFLAGS = -g -Wall + +# list of source and include files +C_SRCS = voParam.c voPkg.c voTask.c voTaskMethod.c voTaskUtil.c +C_OBJS = voParam.o voPkg.o voTask.o voTaskMethod.o voTaskUtil.o +C_INCS = voTask.h voTaskP.h + +C_TASKS = +TARGETS = $(C_TASKS) + +SRCS = $(C_SRCS) +OBJS = $(C_OBJS) +HOST_LIBS = -lcurl -lcfitsio -lpthread -lm +LIBS = -L../../lib $(HOST_LIBS) -lvotable -lsamp -lVOClient -lcfitsio + + +all: + make lib + +World: lib + +install: all + cp lib$(NAME).a $(LIBDIR) + mv $(TARGETS) $(BINDIR) + +objs: $(OBJS) + + +# Targets + +#all: $(TARGETS) + +progs: $(C_TASKS) + +votools: pkgMain.o + $(CC) $(CFLAGS) -o votools.vop pkgMain.c ../libVOApps.a $(LIBS) + /bin/rm -rf *.dSYM + +pylib: + $(CC) $(PYFLAGS) -o voPackage.so voPackage.c + +clean: + /bin/rm -rf .make.state .nse_depinfo *.[aeo] *.dSYM + /bin/rm -rf $(TARGETS) + +everything: + make clean + make all + make install + +help: HELP + +install: all + + + +#################################### +# LIBVOTASK dependency libraries. +#################################### + +lib: objs + ar rv lib$(NAME).a $(OBJS) + $(RM) $(OBJS) + + + +############################################################################### +# Unit test programs to be built. +############################################################################### + +zztest: zztest.c + $(CC) $(CFLAGS) -o zztest zztest.c $(LIBS) + + +########################### +# C Test programs +########################### + + +########################### +# SPP Test programs +########################### + + +########################### +# Fortran Test programs. +########################### + + + + + + +############################################################################### +# Leave this stuff alone. +############################################################################### + +$(STATICLIB): $(C_SRCS:%.c=Static/%.o) + /usr/bin/ar rv $@ $? +Static/%.o: %.c $(C_INCS) + /usr/bin/gcc $(CINCS) $(CFLAGS) -g -c $< -o $@ +Static: + /bin/mkdir $@ + chmod 777 $@ + +$(SHAREDLIB): $(C_SRCS:%.c=Shared/%.o) + /usr/bin/ld -shared -o $@ $? -lc -ldl +Shared/%.o: %.c $(C_INCS) + /usr/bin/gcc $(CINCS) $(CFLAGS) -fpic -shared -c $< -o $@ +Shared: + /bin/mkdir $@ + chmod 777 $@ diff --git a/vendor/voclient/voapps/task/Notes.fitz b/vendor/voclient/voapps/task/Notes.fitz new file mode 100644 index 00000000..fe36e903 --- /dev/null +++ b/vendor/voclient/voapps/task/Notes.fitz @@ -0,0 +1,99 @@ + Client Interface: + ================= + + Package/Task Management: + ------------------------ + + vo_setPkgDir (path) # set package dir + path = vo_getPkgDir () # get package dir + + pkg = vo_pkgList (pattern) # Get available packages + len = vo_pkgLen (pkg) + pkg = vo_pkgNext (pkg) + str = vo_pkgAttr (pkg, attr) + + task = vo_taskList (taskName) # Get tasks in package + len = vo_taskLen (task) + str = vo_taskNext (task) + task = vo_taskAttr (task, attr) + + pp = vo_taskParams (pkgName, taskName) # Input param defs + ( see parameter handling below ) + + xml = vo_pkgXML (pattern) # XML serializations (opt) + xml = vo_taskXML (pkgName) + xml = vo_paramXML (pkgName, taskName) + + + Task Execution: + --------------- + + tp = vo_taskInit (pkgName, taskName) # Initialize a task + + vo_taskSetStringParam (tp, pname, sval) # Set input params + vo_taskSetBoolParam (tp, pname, bval) + vo_taskSetIntParam (tp, pname, ival) + vo_taskSetRealParam (tp, pname, dval) + vo_taskSetDictParam (tp, pname, dict) + vo_taskSetListParam (tp, pname, list) + vo_taskSetPtrParam (tp, pname, ptr, size) + + vo_taskSetCallback (tp, type, &func) # Set param callback + rp = vo_taskExecuteSync (tp, status, msg) # Execute sync + vo_taskExecuteAsync (tp) # Execute async + rp = vo_taskWait (tp) # Wait for task, get RP + status = vo_taskCheckError (tp, msg) # Check for any error + + vo_taskClose (tp) # Free task resources + + Parameter Handling: + ------------------- + + Directed parameter access: + + int = vo_taskParamCount (rp) + vo_taskGetParamInfo (rp, pnum, *name, *type, *encoding, + *description) + str = vo_taskGetStringParam (rp, pname, pnum) # pnum used if pname=null + ival = vo_taskGetBoolParam (rp, pname, pnum) + ival = vo_taskGetIntParam (rp, pname, pnum) + dval = vo_taskGetRealParam (rp, pname, pnum) + dict = vo_taskGetDictParam (rp, pname, pnum) + dict = vo_taskGetListParam (rp, pname, pnum) + void = vo_taskGetParamValue (rp, pname, pnum, size) + + Iterated parameter access: + + pp = vo_taskGetParam (rp, pname, pnum) + len = vo_paramLen (pp, [typ|enc]) + pp = vo_paramNext (pp, [typ|enc]) + str = vo_paramAttr (pp, attr) + + +Notes: +====== + + - Added set/get methods for the package directory to be searched for + packages. This allows a client to point to different dirs depending + on which package is being 'loaded'. + - The pkgList() takes a 'pattern' param to select only files matching a + specific pattern (e.g. "*.e" or "*.pkg") from the working directory. + Only files matching the pattern (or all files if NULL) will be queried + for metadata. This also allows for a directory to contain single-task + binaries and not require a single binary for all tasks in a package. + - Made pkg/task/param listings optionally XML, these are manageable by + many languages but not always 'natural'. The use of iterators allows + a client to traverse the metadata and request attributes w/out depending + on an XML parser. + - Added 'pname' to the setParam() methods to set specific params. + - Added status/msg returns from sync execution + - Input and output parameters share the same data structure and interface + methods work on either. This means a 'blob' can now be an input param, + e.g. an in-memory object (e.g. a target list or TAP ADQL string) from a + client can be posted over IPC to the task. Note however this may not be + implemented for current tasks. + - Parameter callbacks can be set for specific parameter types + - Parameter iterators allow a 'type' or 'encoding' option to find the + next param of the same typ/enc. This allows a client to skip through + output params to find e.g. only FITS objects or only the stdout text + strings and means the callback can be tied to a parameter type easily. diff --git a/vendor/voclient/voapps/task/Notes.tody b/vendor/voclient/voapps/task/Notes.tody new file mode 100644 index 00000000..52b0d514 --- /dev/null +++ b/vendor/voclient/voapps/task/Notes.tody @@ -0,0 +1,164 @@ +VoClient Expanded Tasking Interface +------------------------------------ + + +Current Interface +-------------------------- + +There is a single VOClient "VO" package consisting of a set of tasks +implemented as library functions indexed as an "apps" array of function +pointers. vo_runTask forks a subprocess to execute each task. +Parameters are passed Unix-style as strings (argc,argv[]). A single +result object is returned as a binary byte-counted blob. + +Client: + status = vo_runTask (method, apps[], argc, argv[], *len, +**result) + +Task: + status = vo_setResultFromInt (value, *len, **data) + status = vo_setResultFromReal (value, *len, **data) + status = vo_setResultFromString (value, *len, **data) + +This is ok, a straightforward mapping of the original host CLI task +interface into a programmatic API. However with a little more work we +can generalize this to make the interface self-describing, allowing +generic tasking code to be implemented (all the way up the client +language layer eg Python) and allow new packages/tasks to be addded. + + +Expanded Interface +-------------------------- + +This is an attempt to define the simplest possible interface which is still +general enough to support the package/task paradigm, providing a self +describing capability to allow generic/reusable software to be written to +manipulate and run tasks. The main simplification is that a "package" is +implemented as an executable (a single self contained file) which may +contain multiple tasks and which can be queried to determine its +capabilities. This limits "packages" to implementations which can be self +contained enough to be runnable from a single runtime file, which is +adequate for now to support the VOClient CLI tasks and which can be +generalized later if necessary. + +A "package" is a precompiled executable with a defined API which can be +queried with standard CLI arguments to get package metadata as well as to +run the individual tasks. Metadata queries include user help as in +"-help", plus programatic information such as the package name and +description, list of tasks, task interfaces, builtin help, etc. "Package" +executables are installed in a standard directory which can be examined by +the tasking layer to determine what packages are available. The file names +of package executables follow a simple naming convention so that they can +be easily referenced at runtime. + +Client Interface: + + xml = vo_pkgList () # Available packages + xml = vo_taskList (pkgName) # Tasks in package + xml = vo_taskParams (pkgName, taskName) # Input param set defs + + tp = vo_taskInit (pkgName, taskName) # Prepare to run a task + + vo_taskSetStringParam (tp, sval) # Set input parameters + vo_taskSetBoolParam (tp, sval) + vo_taskSetIntParam (tp, ival) + vo_taskSetRealParam (tp, dval) + + vo_taskSetCallback (tp, &func) # Set callback for output param + rp = vo_taskExecuteSync (tp) # Execute synchronous; returns + # output pset pointer + vo_taskExecuteAsync (tp) # Execute async + rp = vo_taskWait (tp) # Wait for task, get RP + status = vo_taskCheckError (tp, *msg) # Check for any error posted + # to TP or RP + + int = vo_taskOutputParamsCount (rp) # Access output params + vo_taskGetOutputParamInfo (rp, pnum, *name, *type, *encoding, + *description) + + # pnum used if paramName=null + *void = vo_taskGetOutputParamValue (rp, paramName, pnum) +*char = vo_taskGetStringOutputParam (rp, paramName, pnum) + ival = vo_taskGetBoolOutputParam (rp, paramName, pnum) + ival = vo_taskGetIntOutputParam (rp, paramName, pnum) + dval = vo_taskGetRealOutputParam (rp, paramName, pnum) + + vo_taskClose (tp) # Free task resources + +Notes: + 1. vo_pkglist essentially just lists the valid package files in the + package directory. Simple since each package is a single file in + this scheme. + 2. vo_taskInit sets a task context and creates a default/empty param + list. The client sets the params it cares about. When the task + is executed the params are serialized in whatever way the tasking + layer wants to do it internally, e.g. argc/argv. + 3. Tasks can execute either sync or async. In async mode the client + may post a callback handler for output parameters. This is called + during task execution whenever any output parameter (of any name + or type) is set. We can have standard system params stdout (dump + text to stdout), status (running, done), warning (like stderr), + error (task aborted), etc. It is up to the task what parameters + to output. Custom parameters, normally of a standard type/encoding, + are used to return data. + 4. In sync task mode the client waits for completion and gets a + pointer to an output param set which it can walk to process the + output params. Output params can also be retrieved by name if the + client knows what params it expects back. + 5. The client should call vo_taskClose when done to free up task + resources such as output parameters. Otherwise they are retained + indefinitely. + 6. We should define standard values for the param TYPE and ENCODING + e.g., "bool", "int", "image", "fits", "votable", etc.), however + he task may return custom object types or encodings as well which + he client may or may not recognize. + + +Task Interface: # Called by the task itself at runtime + + tp = vo_taskStart () + char *vo_taskGetPackageName (tp) + char *vo_taskGetTaskName (tp) + *char = vo_taskGetStringParam (tp, paramName) + ival = vo_taskGetBoolParam (tp, paramName) + ival = vo_taskGetIntParam (tp, paramName) + dval = vo_taskGetBoolParam (tp, paramName) + + status = vo_setIntOutputParam (tp, paramName, ival) + status = vo_setRealOutputParam (tp, paramName, dval) + status = vo_setStringOutputParam (tp, paramName, sval) + status = vo_setOutputParam (tp, paramName, paramType, paramEncoding, + *len, **void) + tp = vo_taskEnd (tp) + + +Notes: + 1. Task should call vo_taskStart initially to get a runtime context, + and vo_taskEnd when done to free resources, flush any output, and + so forth. + 2. When a task is run in a "connected" (remote) fashion it is passed + a keyword table of parameter values, via argc/argv or whatever. + True host level, CLI (argc/argv) mode can be provided as + well in which case all the -help etc. generics can be provided by + the task main (container). + Defaulting can be performed task-side if provided. + 3. Input parameters can be retrieved by name (do we need to walk a + list as well? probably not in this case). + 4. Output parameters are flushed through to the client in each + setOutputParam call, allowing interactive output at runtime. A + single output parameter may be set multiple times, e.g., + for stdout, warning, status, etc. this could be normal. The + client tasking code accumulates output parameters in an output + param set during execution. Whether or not parameters are passed + on to a client callback is up to the client. + +Whether or not a task executes directly in the client process or in a +separate process is transparent to the client; normally tasks will execute +in a subprocess. + +The main limitation here is the assumption that a "package" is input to the +system as a file. This is simple enough for C code where tasks are just +functions linked into a single executable with a common main. In the +simplest case there is no support for things like task dependencies. +However the single file paradigm can be extended in the future should we +need to do so. diff --git a/vendor/voclient/voapps/task/_pkgbin b/vendor/voclient/voapps/task/_pkgbin new file mode 100644 index 00000000..920b9086 --- /dev/null +++ b/vendor/voclient/voapps/task/_pkgbin @@ -0,0 +1,31 @@ +/** + * + */ + +#include <stdio.h> +#include <stdlib.h> + + +int main (int argc, char *argv[]) +{ + + /* Process arguments. + */ + for (i=1; i < argc; i++) { + switch (argv[i]) { + case 'h': // help + case 'd': // debug + case 'v': // verbose + + case 'a': // package attributes + case 't': // package task list + case 'p': // task parameters ("-p <task>") + + case 'S': // task parameters ("-p <task>") + default: + taskName = argv[i] // execute task .... + } + } + + +} diff --git a/vendor/voclient/voapps/task/mkpy b/vendor/voclient/voapps/task/mkpy new file mode 100755 index 00000000..c8fd62c0 --- /dev/null +++ b/vendor/voclient/voapps/task/mkpy @@ -0,0 +1,5 @@ +#!/bin/csh -f + +set PKG = voPackage + +gcc -dynamiclib -I/usr/include/python2.6/ -lpython2.6 -o $PKG.so $PKG.c diff --git a/vendor/voclient/voapps/task/pkgMain.c b/vendor/voclient/voapps/task/pkgMain.c new file mode 100644 index 00000000..6b616f63 --- /dev/null +++ b/vendor/voclient/voapps/task/pkgMain.c @@ -0,0 +1,117 @@ +/** + * PKG_MAIN -- VOPackage task main(). + * + * @file pkgMain.c + * @author Mike Fitzpatrick + * @date 12/13/12 + * + * @brief VOPackage task main(). + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "votools.h" /* package task declarations */ + + +static int help = 0; /* help flag */ +static int debug = 0; /* debug flag */ +static int verbose = 0; /* verbose flag */ +static int interactive = 0; /* interactive */ +static int connected = 0; /* connected subprocess */ +static int detached = 0; /* detached subprocess */ + +static int do_attrs = 0; /* print package attrs */ +static int do_taskList = 0; /* print task list */ +static int do_taskParams = 0; /* print package attrs */ + +static char *taskName = NULL; /* name of task to execute */ +static char *cbsocket = NULL; /* callback socket */ + + +static void vopHelp(void); + + +static char *opts = "hNno:r%:"; +static struct option long_opts[] = { + { "Number", 2, 0, 'N'}, /* task option */ + { "number", 2, 0, 'n'}, /* task option */ + { "output", 1, 0, 'o'}, /* task option */ + { "return", 2, 0, 'r'}, /* task option */ + { "help", 2, 0, 'h'}, /* required */ + { "test", 1, 0, '%'}, /* required */ + { NULL, 0, 0, 0 } +}; + + + +/** + * Application entry point. + */ +int main (int argc, char *argv[]) +{ + char **pargv, optval[SZ_FNAME], ch; + int pos = 0; + + + /* Process arguments. + */ + pargv = vo_paramInit (argc, argv); + while ((ch = vo_paramNext (opts,long_opts,argc,pargv,optval,&pos)) != 0) { + if (ch > 0) { + switch (ch) { + case 'h': vopHelp (); break; + case 'd': debug++; break; + case 'v': verbose++; break; + + case 'a': /* package attributes */ + do_attrs++; + break; + case 't': /* package task list */ + do_taskList++; + break; + case 'p': /* task parameters ("-p <task>") */ + do_taskParams++; + break; + case 'S': /* callback socket ("-S <sock>") */ + cbsocket = strdup (optval); + break; + } + } else { + taskName = strdup (optval);/* execute task .... */ + } + } + + if (!cbsocket) { + cbsocket = (char *) calloc (1, SZ_FNAME); + sprintf (cbsocket, "/tmp/voPkg_%d", (int) getuid()); + } + + if (!connected && !detached) { /* run interactively */ + interactive++; + } else if (connected) { /* run as a connected process */ + + } else if (detached) { /* run as a detached (bkg) process */ + } + + + if (cbsocket) + free ((void *) cbsocket); + return (0); +} + + +/** + * VOPHELP -- Task help summary. + */ +static void +vopHelp () +{ + printf ("\n\ + Usage: %s [-dhiv] [-a] | [-t] | [-p <task>] -S <cbsock> [<task>]]\n\ + \n\ + ", PKG_NAME); +} + + diff --git a/vendor/voclient/voapps/task/test.py b/vendor/voclient/voapps/task/test.py new file mode 100644 index 00000000..0007da70 --- /dev/null +++ b/vendor/voclient/voapps/task/test.py @@ -0,0 +1,4 @@ + +from voPackage import * + +print vop_taskList ("/tmp/test.vop") diff --git a/vendor/voclient/voapps/task/vaopackage.py b/vendor/voclient/voapps/task/vaopackage.py new file mode 100644 index 00000000..a894e612 --- /dev/null +++ b/vendor/voclient/voapps/task/vaopackage.py @@ -0,0 +1,453 @@ +""" +The VAO Package and Tasking Interfaces. + +The tasking interface defines the python-side classes needed to manage and +execute host processes that implement the "VAO Package" binary interface. +These classes load the package (i.e. execute the binary as a connected +processes and interogate it for a list of available tasks). The VOTask +interface is used to set the input parameters, execute the task and process +the result parameter set (PSet). + +The VOPSet interface manages a collection of VOParam parameter objects: +input parameters will typically define options for the host task (e.g. +input file, processing options, etc), while output parameters may contain +arbitrary objects returned by the task (e.g. a FITS file or VOTable) or +strings which make up the stdout/stderr streams of the task. A VOParam has +attributes needed to describe the type of parameter, by selecting +parameters of the same name from a PSet (e.g. 'msgs') an application can +process multiple output objects as needed. + +A 'task' is a computational component which can be executed as a process by +the host operating system (or a related environment such as a cluster). +Tasks may be written in any language so long as the defined tasking +interface is observed. The 'package' refered to here should not be +confused with a Python package. A Python package is an element of Python, +a 'package' as referred to here is a collection of tasks and their +associated metadata. + +""" + +import sys +import os +import re +import glob + + + +# Module Globals and Functions + +""" The Package search path. +""" +vopkg_path = ['.'] # always include the cwd +vopkg_extn = ".vop" + +pkg_list = [] # scan package dirs to get list of packages +pkg_struct = None # dictionary of package data in the form + # key = pkgname + # value = tuple(<path>, [<tasklist>]) + + +def setPkgDirs (dirs): + ''' Set the VO package search path as an absolute list of directories. + @param dirs list of directory to use as search path + + Returns: Nothing + ''' + vopkg_path = [.] + dirs + + +def addPkgDir (dir): + ''' Append the given directory to the package search path. + @param dir the directory to add to the search path + + Returns: Nothing + ''' + vopkg_path.append(dir) + + +def getPkgDirs (): + ''' Get the VO package search path as a list of directories. + + Returns: Nothing + ''' + return (vopkg_path) + + +def pkgList (pattern=None): + ''' Get the list of available packages. + @param pattern the package name pattern to match + + Returns: A list available package names. + ''' + + pat = pattern # construct the pattern string + if (pattern == None): + pat = "*" + + pkg_list = [] # scan package dirs to get list of packages + for dir in vopkg_path: + if os.path.isdir(dir): + pfiles = glob.glob(dir + "/" + pat + vopkg_extn) + for f in pfiles: + root,ext = os.path.splitext(os.path.basename(f)) + pkg_list.append(root) + pkg_struct[root] = [ f ] + else: + root,ext = os.path.splitext(os.path.basename(dir)) + if (re.search(pattern,root)): + pkg_list.append(root) + pkg_struct[root] = [ dir ] + + # Save just the package names as a valid list. + pkg_list = pkg_struct.keys() + + # Scan the package list, to get a list of tasks in each package. + for pkg in pkg_list: + tlist = vop_taskList (pkg_struct[pkg][0]) # get task list + pkg_struct[pkg].append(tlist) # save in struct + + + +def scan (): + ''' Force a re-scan of the package search path for available package + files. Each directory in the path is searched for a ".vop" file + indicating a VO package executable, this file is then interrogated + for a list of tasks. This allows new package files to be installed + (or removed) as the module is running. + + Returns: Nothing + ''' + lst = pkgList ("*") # scan all packages + + +def loadPackage (name, file=None): + ''' Load the package. Effectively all this does is create a VOPackage + object from the metadata for the named package, this requires + that we start the package binary to get the metadata information. + If a 'file' parameter is specified we open that file regardless of + the name, allowing any VOPackage file to be used dynamically. + + When a package is loaded, bindings for each of the tasks are generated + automatically in order to allow direct access to the task. As an + example: + + >>> vop = loadPackage ("vo-cli") # from search path + >>> results = vop.voregistry (searchTerm="quasar") + >>> printResultPset (results) # user-defined function + + When developing a package or when an app needs to explicitly include + a new package, it may be accessed directly as: + + >>> vop = loadPackage ("vo-cli",file="/path/devpkg.e") + + @param name the package name + @param file the package binary file to execute + + Returns: The loaded VOPackage object + ''' + pass + +def taskList (pkg, pattern=None): + ''' List the tasks available in a package. + @param pkg the package name + @param pattern the task pattern name to match + + Returns: A list of tasks available in the package who's name + matches the 'pattern' string. + ''' + pass + +def pkgAttrs (pkg): + ''' Get the attributes for the named package, i.e. create a dictionary + of package metadata. + @param pkg the package name + + Returns: A dictionary of the package attributes. + ''' + pass + +def taskAttrs (pkg, task): + ''' Get the attributes for the named task in the package, i.e. create + a dictionary of task metadata. + @param pkg the package name + @param task the task name + + Returns: A dictionary of the task attributes. + ''' + pass + + +class VOPackageError (Exception): + ''' A base class for VO Package errors. Use of this exception is TBD. + ''' + pass + + +class VOPackage: + ''' A class defining a VOPackage object. A VOPackage is a collection + of tasks as well as metadata about the package itself. The + functional part of the package is implemented in a binary file + executing as a connected process, task discovery and execution are + implemented as commands sent to the package binary, results are + returned over the IPC channel as a stream of parameter objects. + ''' + + # Class attributes + name = None # package name + descr = None # description string + author = None # package author + contact = None # contact email address + iconUrl = None # URL to package icon + version = None # package version string + dir = None # the directory containing the package + binfile = None # the name of the package binary + + def __init__ (self, dirs): + pass + + def __iter__ (self, dirs): # get next task in the package + pass + + def taskList (self, pattern=None): + ''' Get the list of tasks in the package which match a pattern string. + If no pattern is specified, all tasks are returned. + @param pattern the parameter name to match + + Returns: A list of available tasks who's name matches + the pattern string. + ''' + pass + + def pkgAttrs (self): + ''' Get the attributes for the VO Package as a dictionary string. + + Returns: A dictionary of the package attributes + ''' + pass + + +class VOTaskError (Exception): + ''' A base class for Task execution errors. + ''' + pass + +class VOTaskParameterError (VOTaskError): + ''' an exception indicating an error in the task calling parameters + ''' + pass + +class VOTaskExecutionError (VOTaskError): + ''' an exception indicating an error when executing the task + ''' + pass + + +class VOTask: + ''' A class defining a VO Task object. + ''' + + name = None # task name + pkg = None # parent package name + descr = None # task description string + params = None # task input parameter set + + status = None # task execution return status (OK or ERROR) + msg = None # task execution return error message + + + def __init__ (self, name, pkg, descr, params): + ''' create the VOTask instance + ''' + pass + + def taskAttrs (self): + ''' Get the attributes of the task as a dictionary. + + Returns: A dictionary of the task attributes + ''' + pass + + def setParams (pset): + ''' Set the task parameter pset. Parameters in the pset argument + will be used set the values for the task parameter pset, i.e. + the argument pset can be just a subset of the task parameters, + we'll match the names and set the values for only those params. + If the argument pset contains a parameter not already in the + task input pset, it will be added as a new parameter. + @param pset parameter set to load + + Returns: A dictionary of the task attributes + ''' + pass + + def getParams (): + ''' Set the task parameter pset. + + Returns: The task parameter pset. + ''' + pass + + def setCallback (pattern, func): + ''' Set a callback function to be run whenever a parameter name + that matches the pattern is encountered. Pattern applies only + to the output parameter set. + @param pattern the parameter name to match + @param func the function to be called when parameter encountered + + Returns: nothing + ''' + pass + + def executeSync (self): + ''' Execute the task as a synchronous process. + @throws VOTaskParameterError thrown when parameters are invalid + @throws VOTaskExecutionError thrown when there is an error is + executing a task, e.g. a segfault. + + Returns: The result pset. + ''' + pass + + def executeASync (self): + ''' Execute the task as a asynchronous process. + + Returns: Nothing + ''' + pass + + def wait (self): + ''' Wait for the exit of an asynchronous execution + @throws VOTaskParameterError thrown when parameters are invalid + @throws VOTaskExecutionError thrown when there is an error is + executing a task, e.g. a segfault. + + Returns: The result pset. + ''' + pass + + def status (self): + ''' Get the status of an executing asynchronous task. + + Returns: Task exec status ('Pending','Running','Done','Error') + ''' + pass + + +class VOPset: + ''' A class defining a PSet object. + ''' + + name = None # pset name + pkg = None # package name + task = None # task name associated with pset + description = None # pset description name + + def __init__ (self, name, type, descr, encoding): + ''' create the VOPset instance + ''' + pass + + def loadPset (pkg=None, task=None, saveFile=None): + ''' Load the pset from the named task in the package. If 'saveFile' + is specified the pset is restored from that file. + @param pkg package name + @param task task name + @param saveFile name of the saved parameter file to load + + Returns: The loaded PSet + ''' + pass + + def savePset (saveFile): + ''' Save the PSet to the named file. Serialization of the PSet is + TBD, probably some sort of simple XML schema. + @param saveFile name of the saved parameter file + + Returns: Nothing + ''' + pass + + def paramSet (pattern=None): + ''' Create pset from params who's name matches the 'pattern' string. + If no pattern is specified, all parameters are returned. + @param pattern parameter pattern name to match + + Returns: The constructed PSet + ''' + pass + + def paramList (pattern=None): + ''' Get list of params who's name matches the 'pattern' string. If + no pattern is specified, all parameters are returned. + @param pattern parameter pattern name to match + + Returns: Nothing + ''' + pass + + def addParam (name, type, description, encoding=None): + ''' Add a new parameter with the specified attributes to the pset. + @param name name of the parameter to add + @param type parameter type value + @param descr parameter description string + @param encoding parameter encoding + + Returns: The created parameter + ''' + pass + + def delParam (name): + ''' Delete the named parameter from the pset. + @param name name of the parameter to delete + + Returns: Nothing + ''' + pass + + def getParam (name): + ''' Get the parameter with the given name. + @param name name of the parameter to retrieve + + Returns: Requested parameter + ''' + pass + + +class VOParam: + ''' A class defining a Parameter object. + ''' + + name = None # parameter name + type = None # parameter type (string/int/real/bool/blob) + desc = None # parameter description string + encoding = None # encoding of param (i.e. mime type) + + + def __init__ (self, name, type, descr, encoding): + ''' create the VOParam instance + ''' + pass + + def paramAttrs (): + ''' Get the parameter attributes. + + Returns: A dictionary of parameter attrbutes + ''' + pass + + def getValue (): + ''' Get the value of the parameter (may be a list) + + Returns: The parameter's value + ''' + pass + + def setValue (val): + ''' Set the value of a parameter. + @param val the value of the paramter (arbitrary type) + + Returns: Nothing + ''' + pass + + diff --git a/vendor/voclient/voapps/task/voPackage.c b/vendor/voclient/voapps/task/voPackage.c new file mode 100644 index 00000000..2b53c575 --- /dev/null +++ b/vendor/voclient/voapps/task/voPackage.c @@ -0,0 +1,78 @@ +/** + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <Python.h> + + +typedef struct { +} voPackage; + + + +/** + * VOP_TASKLIST -- List the tasks in the named package. + */ +static PyObject* +vop_taskList (PyObject* self, PyObject* args) /* pkg,pattern=None */ +{ + const char *binpath; + int status; + + if (!PyArg_ParseTuple (args, "s", &binpath)) + return NULL; + + + sts = system(command); + + return Py_BuildValue("s", args); +} + + +/** + * VOP_PKGLIST -- List the packages in the search directory. + */ +static PyObject* +vop_pkgList (PyObject* self, PyObject* args) /* pattern=None */ +{ + char *s = "Hello from vop_pkgList"; + return Py_BuildValue("s", s); +} + +static PyObject* +vop_scan (PyObject* self, PyObject* args) +{ + char *s = "Hello from vop_scan"; + return Py_BuildValue("s", s); +} + +static PyObject* +vop_loadPackage (PyObject* self, PyObject* args) /* name, file=None */ +{ + char *s = "Hello from vop_loadPackage"; + return Py_BuildValue("s", s); +} + +/** ************************************************************************ */ + +/* + * Bind Python function names to our C functions + */ +static PyMethodDef voPackage_methods[] = { + { "vop_taskList", vop_taskList, METH_VARARGS }, + { "vop_pkgList", vop_pkgList, METH_VARARGS }, + { "vop_scan", vop_scan, METH_VARARGS }, + { "vop_loadPackage", vop_loadPackage, METH_VARARGS }, + { NULL, NULL, 0 } +}; + + +/** + * INITVOPACKAGE -- Python calls this to let us initialize our module + */ +void initvoPackage() +{ + (void) Py_InitModule("voPackage", voPackage_methods); +} diff --git a/vendor/voclient/voapps/task/voParam.c b/vendor/voclient/voapps/task/voParam.c new file mode 100644 index 00000000..e5d108ee --- /dev/null +++ b/vendor/voclient/voapps/task/voParam.c @@ -0,0 +1,418 @@ +/** + * + * VOTASK.C -- Utilities to run a VOApps task as a connected subprocess. + * + * + * Expanded Interface + * -------------------------- + * + * This is an attempt to define the simplest possible interface which is still + * general enough to support the package/task paradigm, providing a self + * describing capability to allow generic/reusable software to be written to + * manipulate and run tasks. The main simplification is that a "package" is + * implemented as an executable (a single self contained file) which may + * contain multiple tasks and which can be queried to determine its + * capabilities. This limits "packages" to implementations which can be self + * contained enough to be runnable from a single runtime file, which is + * adequate for now to support the VOClient CLI tasks and which can be + * generalized later if necessary. + * + * A "package" is a precompiled executable with a defined API which can be + * queried with standard CLI arguments to get package metadata as well as to + * run the individual tasks. Metadata queries include user help as in + * "-help", plus programatic information such as the package name and + * description, list of tasks, task interfaces, builtin help, etc. "Package" + * executables are installed in a standard directory which can be examined by + * the tasking layer to determine what packages are available. The file names + * of package executables follow a simple naming convention so that they can + * be easily referenced at runtime. + * + * + * Client Interface: + * ================= + * + * Parameter Handling: + * ------------------- + * + * Directed parameter access: + * + * int = vo_taskParamCount (rp) + * vo_taskGetParamInfo (rp, pnum, *name, *type, *encoding, + * *description) + * str = vo_taskGetStringParam (rp, pname, pnum) # pnum used if pname=null + * ival = vo_taskGetBoolParam (rp, pname, pnum) + * ival = vo_taskGetIntParam (rp, pname, pnum) + * dval = vo_taskGetRealParam (rp, pname, pnum) + * void = vo_taskGetParamValue (rp, pname, pnum, size) + * + * Iterated parameter access: + * + * pp = vo_taskGetParam (rp, pname, pnum) + * len = vo_paramLen (pp, [typ|enc]) + * pp = vo_paramNext (pp, [typ|enc]) + * str = vo_paramAttr (pp, attr) + * + * + * + * @file voParam.c + * @author Mike Fitzpatrick + * @date 9/24/12 + * + * @brief VOClient Tasking Interface. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdarg.h> +#include <setjmp.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <sys/select.h> +#include <sys/time.h> +#include <sys/types.h> +#include "voTask.h" + + + + +/**************************************************************************/ +/*** Package Introspection Methods ***/ +/**************************************************************************/ + +/** + * VO_PKGLIST -- List packages available in the working directory.. + * + * @brief List packages available in the working directory. + * @fn xml = vo_pkgList (char *pattern) + * + * @param pattern Package executable filename pattern (or NULL for all) + * @returns XML description of the package list. + */ +char * +vo_pkgList (char *pattern) +{ + return (NULL); +} + + +/** + * VO_TASKLIST -- List tasks in package. + * + * @brief List tasks in package. + * @fn handle = vo_taskList (char *pkgName) + * + * @param pkgName Package name + * @returns XML description of the task list + */ +char * +vo_taskList (char *pkgName) +{ + return (NULL); +} + + +/** + * VO_TASKPARAMS -- List parameters for a task. + * + * @brief List parameters for a task. + * @fn xml = vo_taskParams (char *pkgName, char *taskName) + * + * @param pkgName Package name + * @param taskName Task name + * @returns XML description of the parameter list + */ +char * +vo_taskParams (char *pkgName, char *taskName) +{ + return (NULL); +} + + +/** + * VO_SETPKGDIR -- Set the working package directory. + * + * @brief Set the working package directory. + * @fn vo_setPkgDir (char *path) + * + * @param path Path to current working package directory + * @returns nothing + */ +void +vo_setPkgDir (char *path) +{ +} + + +/** + * VO_GETPKGDIR -- Get the working package directory. + * + * @brief Get the working package directory. + * @fn path = vo_getPkgDir (void) + * + * @returns path to current working package directory + */ +char * +vo_getPkgDir (void) +{ + return (NULL); +} + + + +/**************************************************************************/ +/*** Task Execution Methods ***/ +/**************************************************************************/ + +/** + * VO_TASKINIT -- Prepare to run a task. + * + * @brief Prepare to run a task. + * @fn handle = vo_taskInit (char *pkgName, char *taskName) + * + * @param pkgName Package name + * @param taskName Task name + * @returns handle to the task descriptor + */ +handle_t +vo_taskInit (char *pkgName, char *taskName) +{ + return (0); +} + + +/** + * VO_TASKSETSTRINGPARAM -- Set a string-valued param. + * + * @brief Set a string-valued param. + * @fn str = vo_taskSetStringParam (handle_t tp, char *paramName, + * char *sval) + * + * @param tp Task handle + * @param paramName Parameter name + * @param sval Parameter value + * @returns nothing + */ +void +vo_taskSetStringParam (handle_t tp, char *paramName, char *sval) +{ +} + + +/** + * VO_TASKSETBOOLPARAM -- Set a bool-valued param. + * + * @brief Set a bool-valued param. + * @fn str = vo_taskSetBoolParam (handle_t tp, char *paramName, int bval) + * + * @param tp Task handle + * @param paramName Parameter name + * @param bval Parameter value (0=false, 1=true) + * @returns nothing + */ +void +vo_taskSetBoolParam (handle_t tp, char *paramName, int bval) +{ +} + + +/** + * VO_TASKSETINTPARAM -- Set a int-valued param. + * + * @brief Set a int-valued param. + * @fn str = vo_taskSetIntParam (handle_t tp, char *paramName, int ival) + * + * @param tp Task handle + * @param paramName Parameter name + * @param ival Parameter value + * @returns nothing + */ +void +vo_taskSetIntParam (handle_t tp, char *paramName, int ival) +{ +} + + +/** + * VO_TASKSETREALPARAM -- Set a real-valued param. + * + * @brief Set a real-valued param. + * @fn str = vo_taskSetRealParam (handle_t tp, char *paramName, + * double rval) + * + * @param tp Task handle + * @param paramName Parameter name + * @param dval Parameter value + * @returns nothing + */ +void +vo_taskSetRealParam (handle_t tp, char *paramName, double dval) +{ +} + + +#ifdef FOO + + vo_taskSetCallback (tp, &func) # Set output param callback + rp = vo_taskExecuteSync (tp) # Execute synchronous; returns + # output pset pointer + vo_taskExecuteAsync (tp) # Execute async + rp = vo_taskWait (tp) # Wait for task, get RP + tatus = vo_taskCheckError (tp, *msg) # Check for any error posted + # to TP or RP +#endif + + + +/**************************************************************************/ +/*** Output Parameters ***/ +/**************************************************************************/ + +/** + * VO_TASKPARAMCOUNT -- Return the number of available output params. + * + * @brief Return the number of available output params. + * @fn status = vo_taskParamCount (handle_t rp) + * + * @param rp Return handle + * @returns Number of available output params + */ +int +vo_taskParamCount (handle_t rp) +{ + return (0); +} + + +/** + * VO_TASKGETPARAMINFO -- Get information about an indexed parameter. + * + * @brief Get information about an indexed parameter. + * @fn status = vo_taskGetParamInfo (handle_t rp, int pnum, + * char *name, char *type, char *encoding, + * char *description) + * + * @param rp Return handle + * @param pnum Parameter index (0-based, used if paramName=NULL) + * @param name Parameter name + * @returns pointer to parameter value + */ +void +vo_taskGetParamInfo (handle_t rp, int pnum, char *name, char *type, + char *encoding, char *description) +{ + return; +} + + +/** + * VO_TASKGETPARAMVALUE -- Get a value of the named/indexed output parameter. + * + * @brief Get a value of the named/indexed output parameter. + * @fn status = vo_taskGetParamValue (handle_t rp, char *paramName, + * int pnum) + * + * @param rp Return handle + * @param paramName Parameter name + * @param pnum Parameter index (0-based, used if paramName=NULL) + * @returns pointer to parameter value + */ +void * +vo_taskGetParamValue (handle_t rp, char *paramName, int pnum) +{ + return ((void *) NULL); +} + + +/** + * VO_TASKGETSTRINGPARAM -- Get a string-valued output parameter. + * + * @brief Get a string-valued output parameter. + * @fn str = vo_taskGetStringParam (handle_t rp, char *paramName, + * int pnum) + * + * @param rp Return handle + * @param paramName Parameter name + * @param pnum Parameter index (0-based, used if paramName=NULL) + * @returns parameter value as a character string + */ +char * +vo_taskGetStringParam (handle_t rp, char *paramName, int pnum) +{ + return ((char *) NULL); +} + + +/** + * VO_TASKGETBOOLPARAM -- Get a bool-valued output parameter. + * + * @brief Get a bool-valued output parameter. + * @fn bval = vo_taskGetBoolParam (handle_t rp, char *paramName, int pnum) + * + * @param rp Return handle + * @param paramName Parameter name + * @param pnum Parameter index (0-based, used if paramName=NULL) + * @returns parameter value as a bool (0=false, 1=true) + */ +int +vo_taskGetBoolParam (handle_t rp, char *paramName, int pnum) +{ + return (0); +} + + +/** + * VO_TASKGETINTPARAM -- Get a int-valued output parameter. + * + * @brief Get a int-valued output parameter. + * @fn ival = vo_taskGetIntParam (handle_t rp, char *paramName, int pnum) + * + * @param rp Return handle + * @param paramName Parameter name + * @param pnum Parameter index (0-based, used if paramName=NULL) + * @returns parameter value and an integer + */ +int +vo_taskGetIntParam (handle_t rp, char *paramName, int pnum) +{ + return (0); +} + + +/** + * VO_TASKGETREALPARAM -- Get a real-valued output parameter. + * + * @brief Get a real-valued output parameter. + * @fn dval = vo_taskGetRealParam (handle_t rp, char *paramName, int pnum) + * + * @param rp Return handle + * @param paramName Parameter name + * @param pnum Parameter index (0-based, used if paramName=NULL) + * @returns parameter value as a double-precision + */ +double +vo_taskGetRealParam (handle_t rp, char *paramName, int pnum) +{ + return ((double) 0.0); +} + + +/** + * VO_TASKCLOSE -- Free task resources. + * + * @brief Free task resources. + * @fn status = vo_taskClose (handle_t tp) + * + * @param tp Task handle + * @returns zero if OK, one on ERROR + */ +int +vo_taskClose (handle_t tp) +{ + return (OK); +} diff --git a/vendor/voclient/voapps/task/voPkg.c b/vendor/voclient/voapps/task/voPkg.c new file mode 100644 index 00000000..9442783b --- /dev/null +++ b/vendor/voclient/voapps/task/voPkg.c @@ -0,0 +1,333 @@ +/** + * + * VOPKG.C -- Task and package management. + * + * This file provides the introspection methods for a callable package. + * These routines are used to call a package binary to get the metadata + * for packages, tasks and parameters. + * + * + * Package/Task Management: + * ------------------------ + * + * vo_setPkgDir (path) # set package dir + * path = vo_getPkgDir () # get package dir + * + * pkg = vo_pkgList (pattern) # Get available packages + * len = vo_pkgLen (pkg) + * pkg = vo_pkgNext (pkg) + * str = vo_pkgAttr (pkg, attr) + * + * pp = vo_pkgParams (pkg) + * pp = vo_taskParams (pkgName, taskName) # Input param defs + * ( see parameter handling below ) + * + * task = vo_taskList (taskName) # Get tasks in package + * len = vo_taskLen (task) + * str = vo_taskNext (task) + * task = vo_taskAttr (task, attr) + * + * + * xml = vo_pkgListXML (pattern) # XML serializations (opt) + * xml = vo_taskListXML (pkgName) + * xml = vo_paramListXML (pkgName, taskName) + * + * + * @file voPkg.c + * @author Mike Fitzpatrick + * @date 9/24/12 + * + * @brief Package and task management methods + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdarg.h> +#include <setjmp.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <sys/select.h> +#include <sys/time.h> +#include <sys/types.h> +#include "voTask.h" + + + + +/**************************************************************************/ +/*** Package Introspection Methods ***/ +/**************************************************************************/ + + +/** + * VO_SETPKGDIR -- Set the working package directory. + * + * @brief Set the working package directory. + * @fn vo_setPkgDir (char *path) + * + * @param path Path to current working package directory + * @returns nothing + */ +void +vo_setPkgDir (char *path) +{ +} + + +/** + * VO_GETPKGDIR -- Get the working package directory. + * + * @brief Get the working package directory. + * @fn path = vo_getPkgDir (void) + * + * @returns path to current working package directory + */ +char * +vo_getPkgDir (void) +{ +} + + +/**************************************************************************/ +/*** Package Management ***/ +/**************************************************************************/ + +/** + * VO_PKGLIST -- List packages available in the working directory.. + * + * @brief List packages available in the working directory. + * @fn xml = vo_pkgList (char *pattern) + * + * @param pattern Package executable filename pattern (or NULL for all) + * @returns XML description of the package list. + */ +handle_t +vo_pkgList (char *pattern) +{ + return (NULL); +} + + +/** + * VO_PKGLIST -- List packages available in the working directory.. + * + * @brief List packages available in the working directory. + * @fn xml = vo_pkgList (char *pattern) + * + * @param pattern Package executable filename pattern (or NULL for all) + * @returns XML description of the package list. + */ +int +vo_pkgLen (handle_t pkg) +{ + Package *pkgP = (Package *) task_H2P (pkg); + + return ( (pkgP ? pkgP->npkgs : 0) ); +} + + +/** + * VO_PKGNEXT -- Get the next package in the list. + * + * @brief Get the next package in the list. + * @fn pkg = vo_pkgNext (handle_t pkg) + * + * @param pkg Handle to package + * @returns Handle to next package in the list (0 at end of list) + */ +handle_t +vo_pkgNext (handle_t pkg) +{ + Package *pkgP = (Package *) task_H2P (pkg); + + return ( (pkgP ? task_P2H (pkgP->next) : 0) ); +} + + +/** + * VO_PKGATTR -- Get a package metadata by attribute name. + * + * @brief Get a package metadata by attribute name. + * @fn pkg = vo_pkgAttr (handle_t pkg, char *attr) + * + * @param pattern Package executable filename pattern (or NULL for all) + * @returns Requested attribute string (or NULL if not found) + */ +char * +vo_pkgAttr (handle_t pkg, char *attr) +{ + Package *pkgP = (Package *) task_H2P (pkg); + + return (NULL); +} + + +/**************************************************************************/ +/*** Task Management ***/ +/**************************************************************************/ + +/** + * VO_TASKLIST -- List tasks in package. + * + * @brief List tasks in package. + * @fn handle = vo_taskList (char *pkgName) + * + * @param pkgName Package name + * @returns XML description of the task list + */ +char * +vo_taskList (char *pkgName) +{ + return (NULL); +} + + +/** + * VO_TASKLEN -- Get length of task list. + * + * @brief Get length of task list. + * @fn len = vo_taskLen (handle_t task) + * + * @param task Handle to task descriptor + * @returns Number of tasks in the list. + */ +int +vo_taskLen (handle_t task) +{ + Package *taskP = (Package *) task_H2P (task); + + return ( (taskP ? taskP->ntasks : 0) ); +} + + +/** + * VO_TASKNEXT -- Get the next task in the list. + * + * @brief Get the next task in the list. + * @fn task = vo_taskNext (handle_t task) + * + * @param task Handle to task + * @returns Handle to next task in the list (0 at end of list) + */ +handle_t +vo_taskNext (handle_t task) +{ + Package *taskP = (Package *) task_H2P (task); + + return ( (taskP ? task_P2H (taskP->next) : 0) ); +} + + +/** + * VO_TASKATTR -- Get a task metadata by attribute name. + * + * @brief Get a task metadata by attribute name. + * @fn task = vo_taskAttr (handle_t task, char *attr) + * + * @param task Handle to task + * @param attr Attribute to retrieve + * @returns Requested attribute string (or NULL if not found) + */ +char * +vo_taskAttr (handle_t task, char *attr) +{ + Package *taskP = (Package *) task_H2P (task); + + return (NULL); +} + + + +/**************************************************************************/ +/*** Task and Package Parameters ***/ +/**************************************************************************/ + +/** + * VO_PKGPARAMS -- List parameters for a package. + * + * @brief List parameters for a package. + * @fn xml = vo_pkgParams (handle_t pkg) + * + * @param pkg Package handle + * @returns XML description of the parameter list + */ +handle_t +vo_pkgParams (handle_t pkg) +{ + return (0); +} + + +/** + * VO_TASKPARAMS -- List parameters for a task. + * + * @brief List parameters for a task. + * @fn xml = vo_taskParams (char *pkgName, char *taskName) + * + * @param pkgName Package name + * @param taskName Task name + * @returns XML description of the parameter list + */ +handle_t +vo_taskParams (char *pkgName, char *taskName) +{ + return (0); +} + + + +/**************************************************************************/ +/*** XML Serializations ***/ +/**************************************************************************/ + +/** + * VO_PKGLISTXML -- Get the package list as an XML document. + * + * @brief Get the package list as an XML document. + * @fn xml = vo_pkgListXML (char *pattern) + * + * @param pattern Package executable pattern + * @returns XML description of the available packages. + */ +char * +vo_pkgListXML (char *pattern) +{ +} + + +/** + * VO_TASKLISTXML -- Get the task list as an XML document. + * + * @brief Get the task list as an XML document. + * @fn xml = vo_taskListXML (char *pkgName) + * + * @param pkgName Package name + * @returns XML description of the tasks in a package. + */ +char * +vo_taskListXML (char *pkgName) +{ +} + + +/** + * VO_PARAMLISTXML -- Get the task parameter list as an XML document. + * + * @brief Get the task parameter list as an XML document. + * @fn xml = vo_paramListXML (char *pkgName, char *taskName) + * + * @param pkgName Package name + * @param taskName Task name + * @returns XML description of the task parameters. + */ +char * +vo_paramListXML (char *pkgName, char *taskName) +{ +} + diff --git a/vendor/voclient/voapps/task/voTask.c b/vendor/voclient/voapps/task/voTask.c new file mode 100644 index 00000000..01de7af1 --- /dev/null +++ b/vendor/voclient/voapps/task/voTask.c @@ -0,0 +1,258 @@ +/** + * + * VOTASK.C -- Utilities to run a VOApps task as a connected subprocess. + * + * + * Client Interface: + * ================= + * + * Task Execution: + * --------------- + * + * tp = vo_taskInit (pkgName, taskName) # Initialize a task + * + * vo_taskSetStringParam (tp, pname, sval) # Set input params + * vo_taskSetBoolParam (tp, pname, bval) + * vo_taskSetIntParam (tp, pname, ival) + * vo_taskSetRealParam (tp, pname, dval) + * vo_taskSetPtrParam (tp, pname, ptr, size) + * + * vo_taskSetCallback (tp, type, &func) # Set param callback + * rp = vo_taskExecuteSync (tp, status, msg) # Execute sync + * vo_taskExecuteAsync (tp) # Execute async + * rp = vo_taskWait (tp) # Wait for task, get RP + * status = vo_taskCheckError (tp, msg) # Check for any error + * + * vo_taskClose (tp) # Free task resources + * + * + * @file voTask.c + * @author Mike Fitzpatrick & Doug Tody + * @date 9/24/12 + * + * @brief VOClient Tasking Interface. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdarg.h> +#include <setjmp.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <sys/select.h> +#include <sys/time.h> +#include <sys/types.h> +#include "voTask.h" + + + + +/**************************************************************************/ +/*** Task Execution Methods ***/ +/**************************************************************************/ + +/** + * VO_TASKINIT -- Prepare to run a task. + * + * @brief Prepare to run a task. + * @fn handle = vo_taskInit (char *pkgName, char *taskName) + * + * @param pkgName Package name + * @param taskName Task name + * @returns handle to the task descriptor + */ +handle_t +vo_taskInit (char *pkgName, char *taskName) +{ +} + + +/** + * VO_TASKSETSTRINGPARAM -- Set a string-valued param. + * + * @brief Set a string-valued param. + * @fn vo_taskSetStringParam (handle_t tp, char *paramName, char *sval) + * + * @param tp Task handle + * @param paramName Parameter name + * @param sval Parameter value + * @returns nothing + */ +void +vo_taskSetStringParam (handle_t tp, char *paramName, char *sval) +{ +} + + +/** + * VO_TASKSETBOOLPARAM -- Set a bool-valued param. + * + * @brief Set a bool-valued param. + * @fn vo_taskSetBoolParam (handle_t tp, char *paramName, int bval) + * + * @param tp Task handle + * @param paramName Parameter name + * @param bval Parameter value (0=false, 1=true) + * @returns nothing + */ +void +vo_taskSetBoolParam (handle_t tp, char *paramName, int bval) +{ +} + + +/** + * VO_TASKSETINTPARAM -- Set a int-valued param. + * + * @brief Set a int-valued param. + * @fn vo_taskSetIntParam (handle_t tp, char *paramName, int ival) + * + * @param tp Task handle + * @param paramName Parameter name + * @param ival Parameter value + * @returns nothing + */ +void +vo_taskSetIntParam (handle_t tp, char *paramName, int ival) +{ +} + + +/** + * VO_TASKSETREALPARAM -- Set a real-valued param. + * + * @brief Set a real-valued param. + * @fn vo_taskSetRealParam (handle_t tp, char *paramName, double rval) + * + * @param tp Task handle + * @param paramName Parameter name + * @param dval Parameter value + * @returns nothing + */ +void +vo_taskSetRealParam (handle_t tp, char *paramName, double dval) +{ +} + + +/** + * VO_TASKSETRAWPARAM -- Set a raw-valued param. + * + * @brief Set a raw-valued param. + * @fn vo_taskSetRawParam (handle_t tp, char *paramName, void *ptr, + * size_t size) + * + * @param tp Task handle + * @param paramName Parameter name + * @param ptr Pointer to raw data block + * @param size Size of data block + * @returns nothing + */ +void +vo_taskSetRawParam (handle_t tp, char *paramName, void *ptr, size_t size) +{ +} + + +/** + * VO_TASKSETCALLBACK -- Set a callback for a parameter type. + * + * @brief Set a callback for a parameter type. + * @fn vo_taskSetCallback (handle_t tp, int type, void *func) + * + * @param tp Task handle + * @param type Parameter type + * @param func Callback function + */ +void +vo_taskSetCallback (handle_t tp, int type, void *func) +{ +} + + +/** + * VO_TASKEXECUTESYNC -- Execute a task synchronously. + * + * @brief Execute a task synchronously. + * @fn rp = vo_taskExecuteSync (handle_t tp, int *status, char *msg) + * + * @param tp Task handle + * @param status Task exit status + * @param msg Buffer for returned error message string + * @returns Handle to output param list + */ +handle_t +vo_taskExecuteSync (handle_t tp, int status, char *msg) +{ +} + + +/** + * VO_TASKEXECUTEASYNC -- Execute a task asynchronously. + * + * @brief Execute a task asynchronously. + * @fn rp = vo_taskExecuteAsync (handle_t tp) + * + * @param tp Task handle + * @returns Handle to output param list + */ +void +vo_taskExecuteAsync (handle_t tp) +{ +} + + +/** + * VO_TASKWAIT -- Wait for an asynchronous task to complete. + * + * @brief Wait for an asynchronous task to complete. + * @fn rp = vo_taskWait (handle_t tp, int *status, char *msg) + * + * @param tp Task handle + * @param status Task exit status + * @param msg Buffer for returned error message string + * @returns Handle to output param list + */ +handle_t +vo_taskWait (handle_t tp, int *status, char *msg) +{ +} + + +/** + * VO_TASKCHECKERROR -- Get the task exit status and (any) error message. + * + * @brief Get the task exit status and (any) error message. + * @fn status = vo_taskCheckError (handle_t tp, char *msg) + * + * @param tp Task handle + * @param msg Buffer for returned error message string + * @returns Task exit status + */ +int +vo_taskCheckError (handle_t tp, char *msg) +{ +} + + + +/** + * VO_TASKCLOSE -- Free task resources. + * + * @brief Free task resources. + * @fn status = vo_taskClose (handle_t tp) + * + * @param tp Task handle + * @returns zero if OK, one on ERROR + */ +int +vo_taskClose (handle_t tp) +{ + return (OK); +} diff --git a/vendor/voclient/voapps/task/voTask.h b/vendor/voclient/voapps/task/voTask.h new file mode 100644 index 00000000..6bedc35e --- /dev/null +++ b/vendor/voclient/voapps/task/voTask.h @@ -0,0 +1,133 @@ +/** + * VOTASK.h -- Tasking interface declarations for the VOClient Package. + * + * @file voTask.h + * @author Mike Fitzpatrick + * @date 9/24/12 + * + * @brief Tasking interface declarations for the VOClient Package. + */ + + +#include <stdio.h> +#include <stdlib.h> + + +typedef int handle_t; + +#ifdef OK +#undef OK +#endif +#define OK 0 + +#ifdef ERR +#undef ERR +#endif +#define ERR 1 + +#ifdef SZ_FORMAT +#undef SZ_FORMAT +#endif +#define SZ_FORMAT 32 + +#ifdef SZ_FNAME +#undef SZ_FNAME +#endif +#define SZ_FNAME 256 + +#ifdef SZ_LINE +#undef SZ_LINE +#endif +#define SZ_LINE 4096 + + +#define MAX_TASKS 128 + + +/* Debug and verbose flags. + */ +#define VOTASK_DEBUG (getenv("VOTASK_DBG")||access("/tmp/VOTASK_DBG",F_OK)==0) +#define VOTASK_VERB (getenv("VOTASK_VERB")||access("/tmp/VOTASK_VERB",F_OK)==0) + +/** + * Output parameter types. + */ +#define FORMATS "|int|rel|string|bool|raw|votable|xml|fits|html|" + +#define TY_INT 1 /* integer */ +#define TY_REAL 2 /* double-precision */ +#define TY_STRING 3 /* string */ +#define TY_BOOL 4 /* bool */ +#define TY_RAW 5 /* blob */ + +#define TY_VOTABLE 6 /* A VOTable */ +#define TY_XML 7 /* A raw XML doc */ +#define TY_FITS 8 /* A FITS file */ +#define TY_HTML 9 /* A HTML doc */ + + + +/* Parameter structure. + */ +typedef struct { + char name[SZ_FNAME]; /* parameter name */ + char descr[SZ_FNAME]; /* parameter description */ + + int type; /* parameter type (int, etc) */ + int encoding; /* parameter encoding */ + int numValues; /* number of parameter values */ + + void *defaultValue; /* default value */ + void *value; /* ptr to value */ + size_t valueLen; /* size of value */ + + void *next; /* next linked-list param */ +} Param, *ParamP; + +typedef struct { + int nParams; /* number of params */ + Param *param; /* parameter itself */ +} PSet, *PSetP; + + + +/* Task structure. + */ +typedef struct { + char name[SZ_FNAME]; /* package name */ + char descr[SZ_FNAME]; /* package description */ + + Param *inParams; /* input params */ + int nInParams; /* number of input params */ + Param *outParams; /* output params */ + int nOutParams; /* number of output params */ + + int status; /* task return status */ + char *msg; /* task return err message */ + + int ntasks; /* number of tasks in list */ + void *next; /* next linked-list task */ +} Task, *TaskP; + + + +/* Package structure. + */ +typedef struct { + char name[SZ_FNAME]; /* package name */ + char descr[SZ_FNAME]; /* package description */ + char author[SZ_FNAME]; /* package author */ + char contact[SZ_FNAME]; /* package contact email */ + char iconUrl[SZ_FNAME]; /* package icon URL */ + char version[SZ_FNAME]; /* package version string */ + + Task tasks[MAX_TASKS]; /* task list */ + int ntasks; /* number of tasks in package */ + Param *params; /* package params */ + int nparams; /* number of package params */ + + char cwd[SZ_FNAME]; /* current working directory */ + + int npkgs; /* number of packages in list */ + void *next; /* next linked-list pkg */ +} Package, *PackageP; diff --git a/vendor/voclient/voapps/task/voTaskMethod.c b/vendor/voclient/voapps/task/voTaskMethod.c new file mode 100644 index 00000000..555d5c96 --- /dev/null +++ b/vendor/voclient/voapps/task/voTaskMethod.c @@ -0,0 +1,49 @@ +/** + * + * + * Task Interface: # Called by the task itself at runtime + * + * tp = vo_taskStart () + * char *vo_taskGetPackageName (tp) + * char *vo_taskGetTaskName (tp) + * *char = vo_taskGetStringParam (tp, paramName) + * ival = vo_taskGetBoolParam (tp, paramName) + * ival = vo_taskGetIntParam (tp, paramName) + * dval = vo_taskGetBoolParam (tp, paramName) + * + * status = vo_setIntOutputParam (tp, paramName, ival) + * status = vo_setRealOutputParam (tp, paramName, dval) + * status = vo_setStringOutputParam (tp, paramName, sval) + * status = vo_setOutputParam (tp, paramName, paramType, paramEncoding, + * *len, **void) + * tp = vo_taskEnd (tp) + * + * + * Notes: + * 1. Task should call vo_taskStart initially to get a runtime context, + * and vo_taskEnd when done to free resources, flush any output, and + * so forth. + * 2. When a task is run in a "connected" (remote) fashion it is passed + * a keyword table of parameter values, via argc/argv or whatever. + * True host level, CLI (argc/argv) mode can be provided as + * well in which case all the -help etc. generics can be provided by + * the task main (container). + * Defaulting can be performed task-side if provided. + * 3. Input parameters can be retrieved by name (do we need to walk a + * list as well? probably not in this case). + * 4. Output parameters are flushed through to the client in each + * setOutputParam call, allowing interactive output at runtime. A + * single output parameter may be set multiple times, e.g., + * for stdout, warning, status, etc. this could be normal. The + * client tasking code accumulates output parameters in an output + * param set during execution. Whether or not parameters are passed + * on to a client callback is up to the client. + * + * Whether or not a task executes directly in the client process or in a + * separate process is transparent to the client; normally tasks will execute + * in a subprocess. + * + */ + +#include "voTask.h" + diff --git a/vendor/voclient/voapps/task/voTaskUtil.c b/vendor/voclient/voapps/task/voTaskUtil.c new file mode 100644 index 00000000..0664da6e --- /dev/null +++ b/vendor/voclient/voapps/task/voTaskUtil.c @@ -0,0 +1,133 @@ +/** + * VOTASKUTIL.C -- Utility methods to convert pointers to user handles. + * + * @brief Utility methods to convert pointers to user handles. + * + * @file voTaskUtil.c + * @author Mike Fitzpatrick + * @date 9/24/12 + */ + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <time.h> +#include <ctype.h> +#include "voTask.h" + + +#define MAX_HANDLES 128 + + +int numHandles = 0; +long taskHandles[MAX_HANDLES]; + +/* Public procedures +*/ +handle_t task_P2H (void *ptr); +void *task_H2P (handle_t handle); +handle_t task_newHandle (void *ptr); +void task_freeHandle (handle_t handle); + + + +/* Utility routines for keep track of handles. +*/ + +/** + * TASK_NEWHANDLE -- Get an unused object handle. + * + * @brief Get an unused object handle + * @fn handle_t task_newHandle (void *ptr) + * + * @param ptr pointer to object to be stored + * @return new object handle + */ +handle_t +task_newHandle (void *ptr) +{ + /* Initialize the handle-to-ptr converter the first time we're called, + ** or whenever we've restarted. + */ + if (numHandles == 0) + memset (taskHandles, 0, sizeof (taskHandles)); + taskHandles[++numHandles] = (long) ptr; + + return (numHandles); +} + + +/** + * TASK_FREEHANDLE -- Free the handle for later re-use. + * + * @brief Free the handle for later re-use. + * @fn task_freeHandle (handle_t handle) + * + * @param handle object handle + * @return nothing + */ +void +task_freeHandle (handle_t handle) +{ + register int i, j; + void *ptr = task_H2P (handle); + + + if (handle <= 0) { + fprintf (stderr, "Error: Attempt to free zero handle!\n"); + return; + } + + for (i=1; i < MAX_HANDLES; i++) { + if ((void *) ptr == (void *) taskHandles[i]) { + for (j=i+1; j < MAX_HANDLES; j++) { + if (taskHandles[j]) + taskHandles[i++] = taskHandles[j]; + else + break; + } + numHandles = ((numHandles-1) >= 0 ? (numHandles-1) : 0); + break; + } + } +} + + +/** + * TASK_P2H -- Convert a pointer to a handle + * + * @brief Convert a pointer to a handle + * @fn handle_t task_P2H (void *ptr) + * + * @param ptr pointer to object + * @return handle to object, < 0 on error + */ +handle_t +task_P2H (void *ptr) +{ + register int i; + + for (i=1; i < MAX_HANDLES; i++) { + if ((void *) ptr == (void *) taskHandles[i]) + return ((int) i); + } + + return (-1); +} + + +/** + * TASK_H2P -- Convert a handle to a pointer + * + * @brief Convert a handle to a pointer + * @fn void *task_H2P (int handle) + * + * @param handle object handle + * @return pointer to object or NULL + */ +void * +task_H2P (handle_t handle) +{ + return ((void *) taskHandles[handle]); +} diff --git a/vendor/voclient/voapps/task/votools.h b/vendor/voclient/voapps/task/votools.h new file mode 100644 index 00000000..3e39ef8d --- /dev/null +++ b/vendor/voclient/voapps/task/votools.h @@ -0,0 +1,79 @@ +/** + * VOTOOLS.H -- VOTools Package Declarations. + * + * @file votools.h + * @author Mike Fitzpatrick + * @date 12/13/12 + * + * @brief VOTools Package Declarations. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* Run as a detached child process? +*/ +#define RUN_DETACHED 0 + + +#define PKG_NAME "votools" + +#include "voApps.h" + +Task *app = (Task *) NULL; + + +/* Task entry-point declarations. + */ +extern int vosamp (int argc, char **argv, size_t *len, void **result); + +extern int votcat (int argc, char **argv, size_t *len, void **result); +extern int votcnv (int argc, char **argv, size_t *len, void **result); +extern int votget (int argc, char **argv, size_t *len, void **result); +extern int votinfo (int argc, char **argv, size_t *len, void **result); +extern int votjoin (int argc, char **argv, size_t *len, void **result); +extern int votpos (int argc, char **argv, size_t *len, void **result); +extern int votsort (int argc, char **argv, size_t *len, void **result); +extern int votsplit (int argc, char **argv, size_t *len, void **result); +extern int votstat (int argc, char **argv, size_t *len, void **result); + +extern int vosesame (int argc, char **argv, size_t *len, void **result); + +extern int vodata (int argc, char **argv, size_t *len, void **result); +extern int voatlas (int argc, char **argv, size_t *len, void **result); +extern int voiminfo (int argc, char **argv, size_t *len, void **result); +extern int vosloanspec (int argc, char **argv, size_t *len, void **result); + +extern int voregistry (int argc, char **argv, size_t *len, void **result); + + +/* Task application table. Applications must be declared here to be found + * and used with the generic main(). + */ + +Task voApps[] = { + { "votcat", votcat }, /* VOTable apps */ + { "votcnv", votcnv }, + { "votget", votget }, + { "votinfo", votinfo }, + { "votjoin", votjoin }, + { "votpos", votpos }, + { "votsort", votsort }, + { "votsplit", votsplit }, + { "votstat", votstat }, + + { "vosamp", vosamp }, /* SAMP messaging */ + + { "vosesame", vosesame }, /* VO Name Resolution */ + + { "vodata", vodata }, /* VO Data access apps */ + { "voatlas", voatlas }, + { "voiminfo", voiminfo }, + { "vosloanspec", vosloanspec }, + + { "voregistry", voregistry }, /* VO Registry apps */ + { NULL, NULL } +}; + + diff --git a/vendor/voclient/voapps/task/zz.c b/vendor/voclient/voapps/task/zz.c new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/vendor/voclient/voapps/task/zz.c diff --git a/vendor/voclient/voapps/task/zz.py b/vendor/voclient/voapps/task/zz.py new file mode 100644 index 00000000..81b61f80 --- /dev/null +++ b/vendor/voclient/voapps/task/zz.py @@ -0,0 +1,60 @@ +import sys +import os +import re +import glob + + +vopkg_path = ['.', "/tmp"] + +pkg_list = [] +pkg_struct = {} + + +def pkgList (pattern=None): + ''' Get the list of available packages. + @param pattern the package name pattern to match + + Returns: A list of available package names. + ''' + + pat = pattern + if (pattern == None): + pat = "*" + + for dir in vopkg_path: + if os.path.isdir(dir): + pfiles = glob.glob(dir + "/" + pat + ".c") + print pfiles + for f in pfiles: + root,ext = os.path.splitext(os.path.basename(f)) + pkg_struct[root] = [ f ] + print f + else: + root,ext = os.path.splitext(os.path.basename(dir)) + if (re.search(pattern,root)): + pkg_struct[root] = [ dir ] + print dir + + # Save just the package names as a valid list. + pkg_list = pkg_struct.keys() + + print pkg_list + print pkg_struct + + +print "vo*" +pkgList("vo*") +print " " + +print "z*" +pkgList("z*") +print " " + +print "None" +pkgList() +print " " + +print "zz" +pkgList("zz") +print " " + diff --git a/vendor/voclient/voapps/task/zztest.c b/vendor/voclient/voapps/task/zztest.c new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/vendor/voclient/voapps/task/zztest.c diff --git a/vendor/voclient/voapps/test.xml b/vendor/voclient/voapps/test.xml new file mode 100644 index 00000000..7acb2cd5 --- /dev/null +++ b/vendor/voclient/voapps/test.xml @@ -0,0 +1,137 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE VOTABLE SYSTEM "http://us-vo.org/xml/VOTable.dtd"> +<VOTABLE version="v1.1"> +<DEFINITIONS> + <COOSYS ID="myJ2000" system="eq_FK5" equinox="2000." epoch="2000."/> +</DEFINITIONS> +<RESOURCE type="results"> + <DESCRIPTION> + Multimission Archive at STScI (MAST) archive.stsci.edu + send questions to: archive@stsci.edu + </DESCRIPTION> +<INFO name="QUERY_STATUS" value="OK"></INFO> +<PARAM ID="id" name="id" value=""></PARAM> +<PARAM name="pos" value="202.468,47.1947" datatype="char" arraysize="*" unit="degrees"> +<DESCRIPTION>Search position in form ra,dec in decimal degrees</DESCRIPTION> +</PARAM> +<PARAM name="size" value="0.2" datatype="double" unit="degrees"> +<DESCRIPTION>Search diameter in decimal degrees</DESCRIPTION> +</PARAM> +<PARAM ID="max_records" name="max_records" value="2000"></PARAM> +<PARAM ID="project" name="project" value="sgal"></PARAM> +<PARAM ID="ra" name="ra" value="202.320834952 .. 202.615165048"></PARAM> +<PARAM ID="dec" name="dec" value="47.0947 .. 47.2947"></PARAM> +<PARAM ID="verb" name="verb" value="1"></PARAM> +<PARAM ID="mission" name="mission" value="siap_keywords"></PARAM> +<PARAM ID="found_rows" name="found_rows" value="20"></PARAM> +<TABLE name="SIAP_KEYWORDS"> +<DESCRIPTION>MAST SIAP_KEYWORDS Search: 6 row(s) returned!</DESCRIPTION> +<FIELD name="filename" datatype="char" ucd="VOX:Image_Title" arraysize="*" ><DESCRIPTION>For HST previews this column contains the dataset name. For HLSP, this column contains the actual filename. + </DESCRIPTION> +</FIELD> +<FIELD name="id" datatype="char" ucd="INST_ID" arraysize="*" ><DESCRIPTION>The instrument ID follows the convention: Archive.Satellite.Instrument + </DESCRIPTION> +</FIELD> +<FIELD name="ra_j2000" datatype="double" ucd="POS_EQ_RA_MAIN" unit="degrees" ref="myJ2000" ><DESCRIPTION>Should be center of image. May not match the Target RA in the FITS header of some HST observations. + </DESCRIPTION> +</FIELD> +<FIELD name="dec_j2000" datatype="double" ucd="POS_EQ_DEC_MAIN" unit="degrees" ref="myJ2000" ><DESCRIPTION>Should be center of image. May not match the Target Dec in the FITS header of some HST observations. + </DESCRIPTION> +</FIELD> +<FIELD name="url" datatype="char" ucd="VOX:Image_AccessReference" arraysize="*" ><DESCRIPTION>URL of image file + </DESCRIPTION> +</FIELD> +<FIELD name="filesize" datatype="int" ucd="VOX:Image_FileSize" unit="bytes" ><DESCRIPTION>File size in bytes + </DESCRIPTION> +</FIELD> +<FIELD name="mjdmean" datatype="double" ucd="VOX:Image_MJDateObs" unit="days" ><DESCRIPTION>Observation midpoint as Modifed Julian Date + </DESCRIPTION> +</FIELD> +<FIELD name="naxes" datatype="int" ucd="VOX:Image_Naxes" ><DESCRIPTION>Number of axes + </DESCRIPTION> +</FIELD> +<FIELD name="naxis" datatype="int" ucd="VOX:Image_Naxis" unit="pixels" arraysize="*" ><DESCRIPTION>image size in pixels + </DESCRIPTION> +</FIELD> +<FIELD name="scale" datatype="double" ucd="VOX:Image_Scale" unit="degrees/pixel" arraysize="*" ><DESCRIPTION>Image scale in deg/pixel for each axis (as a concatenated string) + </DESCRIPTION> +</FIELD> +<FIELD name="cd" datatype="double" ucd="VOX:WCS_CDMatrix" unit="degrees/pixel" arraysize="*" ><DESCRIPTION>CD matrix (values concatenated into a single character field) + </DESCRIPTION> +</FIELD> +<FIELD name="format" datatype="char" ucd="VOX:Image_Format" arraysize="*" ><DESCRIPTION>Mime type of file + </DESCRIPTION> +</FIELD> +<FIELD name="ref_frame" datatype="char" ucd="VOX:STC_CoordRefFrame" arraysize="*" ><DESCRIPTION>coordinate system reference frame + </DESCRIPTION> +</FIELD> +<FIELD name="equinox" datatype="float" ucd="VOX:STC_CoordEquinox" unit="years" ><DESCRIPTION>Equinox + </DESCRIPTION> +</FIELD> +<FIELD name="coord_projection" datatype="char" ucd="VOX:WCS_CoordProjection" arraysize="3" ><DESCRIPTION>celestial projection used + </DESCRIPTION> +</FIELD> +<FIELD name="crpix" datatype="double" ucd="VOX:WCS_CoordRefPixel" unit="pixels" arraysize="*" ><DESCRIPTION>image coordinates of WCS reference pixel (crpix) + </DESCRIPTION> +</FIELD> +<FIELD name="crval" datatype="double" ucd="VOX:WCS_CoordRefValue" unit="pixels" arraysize="*" ><DESCRIPTION>world coordinates of WCS reference pixel (crval) + </DESCRIPTION> +</FIELD> +<FIELD name="ctype" datatype="char" ucd="ID_FIELD" arraysize="*" ><DESCRIPTION>Axes labels (ctype) + </DESCRIPTION> +</FIELD> +<FIELD name="bandpass_id" datatype="char" ucd="VOX:BandPass_ID" arraysize="*" ><DESCRIPTION>Filter Designation + </DESCRIPTION> +</FIELD> +<FIELD name="bandpass_refvalue" datatype="double" ucd="VOX:BandPass_RefValue" unit="meters" ><DESCRIPTION>approximate central wavelength or frequency + </DESCRIPTION> +</FIELD> +<FIELD name="bandpass_unit" datatype="char" ucd="VOX:BandPass_Unit" unit="meters" arraysize="*" ><DESCRIPTION>VLAFIRST uses frequencies (hertz), other missions use wavelengths (meters) + </DESCRIPTION> +</FIELD> +<FIELD name="bandpass_hilimit" datatype="double" ucd="VOX:BandPass_HiLimit" unit="meters" ><DESCRIPTION>bandpass upper limit + </DESCRIPTION> +</FIELD> +<FIELD name="bandpass_lolimit" datatype="double" ucd="VOX:BandPass_LoLimit" unit="meters" ><DESCRIPTION>bandpass lower limit + </DESCRIPTION> +</FIELD> +<FIELD name="processing" datatype="char" ucd="VOX:Image_PixFlags" arraysize="*" ><DESCRIPTION>level of processing + </DESCRIPTION> +</FIELD> +<FIELD name="project" datatype="char" ucd="ID_GROUP" arraysize="*" ><DESCRIPTION>hlsp indicator + </DESCRIPTION> +</FIELD> +<FIELD name="preview" datatype="char" ucd="ID_GROUP" arraysize="*" ><DESCRIPTION>indicates a preview is available + </DESCRIPTION> +</FIELD> +<FIELD name="representative" datatype="char" ucd="ID_GROUP" arraysize="*" ><DESCRIPTION>indicates a scrapbook selection + </DESCRIPTION> +</FIELD> +<FIELD name="object_id" datatype="char" ucd="ID_TARGET" arraysize="*" ><DESCRIPTION>Target name + </DESCRIPTION> +</FIELD> +<DATA> +<TABLEDATA> +<TR> +<TD>dpix1.fits</TD><TD>MAST.HST.WFPC2</TD><TD>202.504583333</TD><TD>47.22861</TD><TD><![CDATA[http://iraf.noao.edu/votest/dpix1.fits]]></TD><TD>16777216</TD><TD></TD><TD>2</TD><TD>512 512</TD><TD>-9.929466E-7 9.871683E-7</TD><TD>-9.929466E-7 1.379957E-5 1.378579E-5 9.871683E-7</TD><TD>image/fits</TD><TD>FK4</TD><TD>2000.000</TD><TD>TAN</TD><TD>1069.018 1065.018</TD><TD>202.5111118072 47.24408628</TD><TD>RA---TAN DEC--TAN</TD><TD>F814W</TD><TD>8.002e-7</TD><TD>meters</TD><TD>8.326e-7</TD><TD>7.677e-7</TD><TD>Z</TD><TD>sgal</TD><TD></TD><TD>n</TD><TD>M51-ULX2</TD> +</TR> +<TR> +<TD>dpix2.fits</TD><TD>MAST.HST.WFPC2</TD><TD>202.504583333</TD><TD>47.22861</TD><TD><![CDATA[http://iraf.noao.edu/votest/dpix2.fits]]></TD><TD>16777216</TD><TD></TD><TD>2</TD><TD>512 512</TD><TD>6.303785E-6 -6.301675E-6</TD><TD>6.303785E-6 4.861660E-7 4.971642E-7 -6.301675E-6</TD><TD>image/fits</TD><TD>FK4</TD><TD>2000.000</TD><TD>TAN</TD><TD>1063.037 1072.028</TD><TD>202.5045833333 47.22861111111</TD><TD>RA---TAN DEC--TAN</TD><TD>F555W</TD><TD>5.443e-7</TD><TD>meters</TD><TD>5.704e-7</TD><TD>5.182e-7</TD><TD>Z</TD><TD>sgal</TD><TD></TD><TD>n</TD><TD>M51-ULX2</TD> +</TR> +<TR> +<TD>dpix3.fits</TD><TD>MAST.HST.WFPC2</TD><TD>202.504583333</TD><TD>47.22861</TD><TD><![CDATA[http://iraf.noao.edu/votest/dpix3.fits]]></TD><TD>16777216</TD><TD></TD><TD>2</TD><TD>512 512</TD><TD>6.302246E-6 -6.300137E-6</TD><TD>6.302246E-6 4.860486E-7 4.970415E-7 -6.300137E-6</TD><TD>image/fits</TD><TD>FK4</TD><TD>2000.000</TD><TD>TAN</TD><TD>1063.047 1072.041</TD><TD>202.5045833333 47.22861111111</TD><TD>RA---TAN DEC--TAN</TD><TD>F814W</TD><TD>7.996e-7</TD><TD>meters</TD><TD>8.319e-7</TD><TD>7.673e-7</TD><TD>Z</TD><TD>sgal</TD><TD></TD><TD>n</TD><TD>M51-ULX2</TD> +</TR> +<TR> +<TD>dpix4.fits</TD><TD>MAST.HST.WFPC2</TD><TD>202.504583333</TD><TD>47.22861</TD><TD><![CDATA[http://iraf.noao.edu/votest/dpix4.fits]]></TD><TD>16777216</TD><TD></TD><TD>2</TD><TD>512 512</TD><TD>-1.377966E-5 1.376732E-5</TD><TD>-1.377966E-5 -1.125826E-6 -1.133609E-6 1.376732E-5</TD><TD>image/fits</TD><TD>FK4</TD><TD>2000.000</TD><TD>TAN</TD><TD>1095.02 1072.024</TD><TD>202.479449437 47.24240418885</TD><TD>RA---TAN DEC--TAN</TD><TD>F814W</TD><TD>8.012e-7</TD><TD>meters</TD><TD>8.339e-7</TD><TD>7.685e-7</TD><TD>Z</TD><TD>sgal</TD><TD></TD><TD>n</TD><TD>M51-ULX2</TD> +</TR> +<TR> +<TD>dpix5.fits</TD><TD>MAST.HST.WFPC2</TD><TD>202.504583333</TD><TD>47.22861</TD><TD><![CDATA[http://iraf.noao.edu/votest/dpix5.fits]]></TD><TD>16777216</TD><TD></TD><TD>2</TD><TD>512 512</TD><TD>1.206699E-6 -1.201142E-6</TD><TD>1.206699E-6 -1.377713E-5 -1.376330E-5 -1.201142E-6</TD><TD>image/fits</TD><TD>FK4</TD><TD>2000.000</TD><TD>TAN</TD><TD>1070.015 1051.016</TD><TD>202.482657254 47.22173504583</TD><TD>RA---TAN DEC--TAN</TD><TD>F814W</TD><TD>7.983e-7</TD><TD>meters</TD><TD>8.303e-7</TD><TD>7.664e-7</TD><TD>Z</TD><TD>sgal</TD><TD></TD><TD>n</TD><TD>M51-ULX2</TD> +</TR> +<TR> +<TD>dpix6.fits</TD><TD>MAST.HST.WFPC2</TD><TD>202.504583333</TD><TD>47.22861</TD><TD><![CDATA[http://iraf.noao.edu/votest/dpix6.fits]]></TD><TD>67108864</TD><TD></TD><TD>2</TD><TD>4096 4096</TD><TD>-1.376853E-5 1.376211E-5</TD><TD>-1.376853E-5 -1.112365E-6 -1.136848E-6 1.376211E-5</TD><TD>image/fits</TD><TD>FK4</TD><TD>2000.000</TD><TD>TAN</TD><TD>1772.441 1803.596</TD><TD>202.5045833333 47.22861111111</TD><TD>RA---TAN DEC--TAN</TD><TD>F814W</TD><TD>7.996e-7</TD><TD>meters</TD><TD>8.319e-7</TD><TD>7.673e-7</TD><TD>Z</TD><TD>sgal</TD><TD></TD><TD>n</TD><TD>M51-ULX2</TD> +</TR> +</TABLEDATA> +</DATA> +</TABLE> +</RESOURCE> +</VOTABLE> diff --git a/vendor/voclient/voapps/test/_tasks b/vendor/voclient/voapps/test/_tasks new file mode 100644 index 00000000..0e779b26 --- /dev/null +++ b/vendor/voclient/voapps/test/_tasks @@ -0,0 +1,17 @@ +voatlas +vocatalog +vodata +voimage +voiminfo +voregistry +vosamp +vosesame +vosloanspec +vospectra +votcnv +votget +votinfo +votopic +votpos +votsort +votstat diff --git a/vendor/voclient/voapps/test/_tests b/vendor/voclient/voapps/test/_tests new file mode 100644 index 00000000..9f169eb6 --- /dev/null +++ b/vendor/voclient/voapps/test/_tests @@ -0,0 +1,167 @@ +# voatlas -- done + voatlas -S m83 or + voatlas --samp m83 + + voatlas -o gal.jpg -n 256 --graphic sombrero + voatlas -s 20m --survey=wise22 m101 + voatlas --band=radio 3c273 + voatlas --survey=list -v ngc1234 + +# vocatalog -- done + vocatalog gsc2.3 ngc1234 (a) + vocatalog gsc2.3 pos.txt (b) + vocatalog gsc2.3 m31,m51,m93 (c) + vocatalog svcs.txt pos.txt (d) + vocatalog hst,chandra,gsc2.3 pos.txt (e) + vocatalog -count -b x-ray any abell2712\n\ + +# vodata -- done, need to verify results + vodata gsc2.3 ngc1234 (a) + vodata gsc2.3 pos.txt (b) + vodata gsc2.3 m31,m51,m93 (c) + vodata svcs.txt pos.txt (d) + vodata hst,chandra,gsc2.3 pos.txt (e) + + vodata -c -t image any IC10 + vodata --count --type=image any IC10 + vodata -c -t catalog -b x-ray any abell2712 + vodata --count --type=catalog --bandpass=x-ray any abell2712 + + vodata --meta rc3 or vodata -m rc3 + + voregistry cooling flow + vodata -O white97 -all J/MNRAS/292/419 + vodata --output=white97 --all J/MNRAS/292/419 + + voregistry -rv -t image xmm + vodata -cq xmm-newton 3c273 + vodata --count --quiet xmm-newton 3c273 + vodata --get xmm-newton 3c273 + + vodata -e -O 2mass -t image 2mass 12:34:56.7 -23:12:45.2 + vodata -e --output=2mass --type=image 2mass 12:34:56.7 -23:12:45.2 + grep fits 2mass_I_001_15998.urls > images.txt + vodata images.txt + grep fits 2mass_I_001_15998.urls | vodata -i - + + vodata -t image -s http://localhost/siap.pl 180.0 0.0 + vodata --type=image --svc=http://localhost/siap.pl 180.0 0.0 + + voregistry -v -v --type=catalog abell | less + vodata -e ivo://nasa.heasarc/abell 0.0 0.0 180.0 + vodata --extract ivo://nasa.heasarc/abell 0.0 0.0 180.0 + + cut -c6- *.pos | vodata ivo://nasa.heasarc/chanmaster -p - + cut -c6- *.pos | vodata ivo://nasa.heasarc/chanmaster --pos=- + vodata -cq chandra -i - + stilts tpipe ifmt=votable qso_survey.vot \ + + wcsinfo *.fits | vodata 2mass-psc -i - + wcsinfo -pos_only *.fits > centers.txt + vodata --sr=25m 2mass-psc centers.txt + + cat cmds.txt + vodata -i cmds.txt + + vodata -a galex M51 + vodata --all galex M51 + + vodata gsc2.3 positions.txt + vodata --cols=2,3,1 --hskip=5 gsc2.3 positions.txt + +# voimage -- done + voimage -b x-ray any m51 + voimage -c HSTAEC IC10 + +# voiminfo -- done + votiminfo -n mef.fits + voiminfo -b -s image.fits + voiminfo -c image.fits\n" + voiminfo -b -f pos.txt mef.fits\n" + +# voregistry -- done, need to verify results + voregistry -count -t image + voregistry -rv -t image + voregistry -t catalog radio galaxies + voregistry -list GSC2.2 + voregistry -b radio abell + voregistry -rvv -n 1 J/A+A/446/97/tab + voregistry -v -t image wfpc + voregistry -cv keck + voregistry -c chandra hst spitzer + voregistry -co chandra hst spitzer + voregistry -meta gsc2.2 + voregistry "Facility like 'HST'" + voregistry "Title like '%Keck%'" + cat query.txt + cat query.txt | voregistry + voregistry --new 3m + voregistry --new 3m cool stars + voregistry --updated 12m --count + +# vosamp -- done + vosamp load /path/example.xml + vosamp load http://foo.edu/example.xml + vosamp load http://foo.edu/query?RA=0.0&DEC=0.0&SR=0.1 + vosamp -t iraf exec "display dev$pix 1" + vosamp list + +# vosesame -- done + vosesame ngc4456 + vosesame -s ngc4456 + vosesame -st m31 m51 m99 + vosesame -CHndt myobjs.txt + cut -c17-25 data.txt | vosesame -ns + vosesame -a + vosesame -sd -c 12:30:0.0 -45:00:0.0 -c 187.5 2.05 + +# vosloanspec -- done, service is unreliable though + vosloanspec -s 0.1 -t galaxy 'Hubble Deep Field' + vosloanspec --size=0.1 --type=galaxy 'Hubble Deep Field' + vosloanspec -m -d m51 + vosloanspec --meta --delete m51 + vosloanspec -l 5 --samp 3c273 # as a spectrum msg + vosloanspec -l 5 --samp --table 3c273 # as a table msg + vosloanspec --redshift=0.3-1.0 + +# vospectra -- done, need more examples + vospectra any 3c273 + +# votcnv -- done + votcnv --fmt=csv test.xml + votcnv -f vot -i 2 test.xml + votcnv -f vot -i 0 test.xml + +# votget -- done + votget -N 3 results.xml + votget -b foo -e fits -S + votget -b foo urls.txt + votget -x results.xml + +# votinfo -- done + votinfo -v test.xml + votinfo -p test.xml + votinfo --numberOf=param test.xml + votinfo -q test.xml + +# votopic -- done, needs more examples + votopic -t catalog lens A2712 + voregistry -t catalog -d -o lens.xml lens + vodata lens.xml A2712 + +# votpos -- done + votpos test.xml + votpos -n test.xml + cat test.xml | votpos + votpos -o pos.txt test.xml + +# votsort -- done + votsort test.xml + votsort http://generic.edu/test.xml + cat test.xml | votsort -o sort_test.xml + votsort --name=V test.xml + votsort --name=V --desc --top=10 test.xml + votsort -s -f csv test.xml + votsort --string --fmt=csv test.xml + votstat test.xml + votsort -a -o stats test.xml diff --git a/vendor/voclient/voapps/test/gal.jpg b/vendor/voclient/voapps/test/gal.jpg Binary files differnew file mode 100644 index 00000000..1e769c79 --- /dev/null +++ b/vendor/voclient/voapps/test/gal.jpg diff --git a/vendor/voclient/voapps/test/test.voatlas b/vendor/voclient/voapps/test/test.voatlas new file mode 100755 index 00000000..16601464 --- /dev/null +++ b/vendor/voclient/voapps/test/test.voatlas @@ -0,0 +1,10 @@ +#!/bin/csh -fx + + voatlas -S m83 + voatlas --samp m83 + + voatlas -o gal.jpg -n 256 --graphic sombrero + voatlas -s 20m --survey=wise22 m101 + voatlas --band=radio 3c273 + voatlas --survey=list -v ngc1234 + diff --git a/vendor/voclient/voapps/voApps.c b/vendor/voclient/voapps/voApps.c new file mode 100644 index 00000000..b48d974f --- /dev/null +++ b/vendor/voclient/voapps/voApps.c @@ -0,0 +1,137 @@ +/** + * VOAPPS.C -- Generic task main() for the VOClient Package applications. + * + * @file voApps.c + * @author Mike Fitzpatrick + * @date 6/03/11 + * + * @brief Generic task main() for the VOClient Package applications. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* Run as a detached child process? +*/ +#define RUN_DETACHED 0 + + +#include "voApps.h" + +Task *app = (Task *) NULL; + + +/* Task entry-point declarations. + */ +extern int vosamp (int argc, char **argv, size_t *len, void **result); + +/*** NOT YET IMPLEMENTED *** +extern int votcat (int argc, char **argv, size_t *len, void **result); +extern int votjoin (int argc, char **argv, size_t *len, void **result); +extern int votselect (int argc, char **argv, size_t *len, void **result); +extern int votsplit (int argc, char **argv, size_t *len, void **result); +****/ +extern int votcnv (int argc, char **argv, size_t *len, void **result); +extern int votget (int argc, char **argv, size_t *len, void **result); +extern int votinfo (int argc, char **argv, size_t *len, void **result); +extern int votpos (int argc, char **argv, size_t *len, void **result); +extern int votsort (int argc, char **argv, size_t *len, void **result); +extern int votstat (int argc, char **argv, size_t *len, void **result); + +extern int vosesame (int argc, char **argv, size_t *len, void **result); + +extern int voatlas (int argc, char **argv, size_t *len, void **result); +extern int vocatalog (int argc, char **argv, size_t *len, void **result); +extern int vodata (int argc, char **argv, size_t *len, void **result); +extern int voimage (int argc, char **argv, size_t *len, void **result); +extern int voiminfo (int argc, char **argv, size_t *len, void **result); +extern int vospectra (int argc, char **argv, size_t *len, void **result); +extern int votopic (int argc, char **argv, size_t *len, void **result); + +extern int voregistry (int argc, char **argv, size_t *len, void **result); + + +/* Task application table. Applications must be declared here to be found + * and used with the generic main(). + */ + +Task voApps[] = { + /*** NOT YET IMPLEMENTED **** + { "votcat", votcat }, + { "votjoin", votjoin }, + { "votselect", votselect }, + { "votsplit", votsplit }, + ****/ + + { "votcnv", votcnv }, /* VOTable apps */ + { "votget", votget }, + { "votinfo", votinfo }, + { "votpos", votpos }, + { "votsort", votsort }, + { "votstat", votstat }, + + { "vosamp", vosamp }, /* SAMP messaging */ + + { "vosesame", vosesame }, /* VO Name Resolution */ + + { "voatlas", voatlas }, /* VO Data access apps */ + { "vocatalog", vocatalog }, + { "vodata", vodata }, + { "voimage", voimage }, + { "voiminfo", voiminfo }, + { "vospectra", vospectra }, + { "votopic", votopic }, + + { "voregistry", voregistry }, /* VO Registry apps */ + { NULL, NULL } +}; + + + +/** + * Program main(). + */ +int +main (int argc, char *argv[]) +{ + char *task = (char *) NULL; + int status = 0; + size_t reslen = 0; + void *result = (void *) NULL; + + + /* Get the task name minus any leading path prefix. + */ + task = argv[0] + strlen (argv[0]) - 1; + while (task > argv[0]) { + if ( *(task - 1) != '/') + task--; + else + break; + } + + /* Loop through the application table. If the names match, call + * the entry-point function. + */ + if (getenv ("VOAPP_CONNECTED") || (! RUN_DETACHED) ) { + for (app = voApps; app->name; app++) { + if (strcmp (app->name, task) == 0) { + status = (*app->func) (argc, argv, &reslen, &result); + break; + } + } + } else { + /* Run as a detached sub-process. + */ + status = vo_runTask (task, voApps, argc, argv, &reslen, &result); + } + + + if (status && result) /* print the error message */ + fprintf (stderr, "%s\n", (char *) result); + if (reslen && result) /* free result pointer */ + free (result); + + return (status); +} diff --git a/vendor/voclient/voapps/voApps.h b/vendor/voclient/voapps/voApps.h new file mode 100644 index 00000000..f5ad6cca --- /dev/null +++ b/vendor/voclient/voapps/voApps.h @@ -0,0 +1,180 @@ +/** + * VOAPPS.h -- Task declarations for the VOClient Package applications. + * + * @file voApps.h + * @author Mike Fitzpatrick + * @date 6/03/11 + * + * @brief Task declarations for the VOClient Package applications. + */ + + +#include <getopt.h> + + +#ifdef SZ_FORMAT +#undef SZ_FORMAT +#endif +#define SZ_FORMAT 32 + +#ifdef SZ_FNAME +#undef SZ_FNAME +#endif +#define SZ_FNAME 256 + +#ifdef SZ_PATH +#undef SZ_PATH +#endif +#define SZ_PATH 512 + +#ifdef SZ_LINE +#undef SZ_LINE +#endif +#define SZ_LINE 4096 + +#define PARG_ERR -127 + +#define dabs(x) ((x<0.0?-x:x)) + +/* Debug and verbose flags. + */ +#define VOAPP_DEBUG (getenv("VOAPP_DBG")||access("/tmp/VOAPP_DBG",F_OK)==0) +#define VOAPP_VERB (getenv("VOAPP_VERB")||access("/tmp/VOAPP_VERB",F_OK)==0) + +/** + * Output formats. + */ +#define FORMATS "|vot|asv|bsv|csv|tsv|html|shtml|fits|ascii|xml|raw|" + +#define VOT 0 /* A new VOTable */ +#define ASV 1 /* ascii separated values */ +#define BSV 2 /* bar separated values */ +#define CSV 3 /* comma separated values */ +#define TSV 4 /* tab separated values */ +#define HTML 5 /* standalone HTML document */ +#define SHTML 6 /* single HTML <table> */ +#define FITS 7 /* FITS binary table */ +#define ASCII 8 /* ASV alias */ +#define XML 9 /* VOTable alias */ +#define RAW 10 /* " " */ + + + +/* SAMP Definitions. + */ +#define SESS_CALLBACK 0 /* mgr sends callback port */ +#define SESS_QUIT 1 /* mgr sends quit/client quits */ +#define SESS_SEND 2 /* mgr/client forwards cmd */ +#define SESS_READY 3 /* mgr ready on port */ + +#define SESS_DEFPORT 3000 /* default session mgr port */ +#define SESS_DEFHOST "140.252.1.86" /* default session mgr host */ + +#define SAMP_CMD 000 /* message is a command */ +#define SAMP_DATA 001 /* message is data file */ +#define SAMP_RESULT 002 /* message is cmd result */ +#define SAMP_QUIT 004 /* message is quit request */ +#define SAMP_RELAY 010 /* message is relayed */ +#define SAMP_TEST 020 /* message is a test connect */ + + +/* File Formats. + */ +#define VOT_FITS 0 +#define VOT_VOTABLE 1 +#define VOT_FITS_SPEC 2 +#define VOT_VOTABLE_SPEC 3 + +/* URL Formats. + */ +#define VOS_LOCALURL 0 /* e.g. http://127.0.0.1/foo */ +#define VOS_LOCALURI 1 /* e.g. file:///path/foo */ +#define VOS_LOCALFILE 2 /* e.g. /path/foo */ +#define VOS_REMOTE 3 /* e.g. http://foo.bar/junk */ + + + +/****************************************************************************** + * Image information structure. Note that although we can report 3-D + * images, we're really only setup to deal with equatorial sky coord + * systems. + *****************************************************************************/ +typedef struct { + char *imname; /* image name */ + int is_image; /* is it an image? */ + int is_table; /* is it a table? */ + int has_wcs; /* image has wcs */ + + int extnum; /* extension number */ + int naxis; /* number of axes */ + int naxes[3]; /* axis dimensions */ + int bitpix; /* pixel size */ + int axflip; /* are axes flipped? */ + + double xc[4], yc[4]; /* corner positions (wcs) */ + double cx, cy; /* center position (wcs) */ + double lx, ly; /* LL corner (wcs) */ + double ux, uy; /* UR corner (wcs) */ + double xrval, yrval; /* CRVAL values */ + double xrpix, yrpix; /* CRPIX values */ + + double width, height; /* image width/height (deg) */ + double radius; /* cone radius (deg) */ + double rotang; /* rotation angle (deg) */ + double scale; /* plate scale (""/pix) */ + char ctype[5]; /* coordinate type */ +} frameInfo, *frameInfoP; + +typedef struct { + char imname[SZ_PATH]; /* full image name */ + int nextend; /* number of extensions */ + + frameInfo frame; /* full frame information */ + frameInfo *extns; /* image extn information */ +} ImInfo, *ImInfoP; + + +ImInfo *vot_imageInfo (char *name, int do_all); +void vot_printImageInfo (FILE *fd, ImInfo *im); +int vot_imageNExtns (char *image); +void vot_freeImageInfo (ImInfo *img); + + + +/* 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; + + +/* Tasking execution procedure. + */ +int vo_runTask (char *method, Task *apps, int argc, char **argv, size_t *len, + void **result); +int vo_taskTest (Task *self, char *arg, ...); +void vo_taskTestFile (char *str, char *fname); +void vo_taskTestReport (Task self); +void vo_taskDbg (void); + +int vo_setResultFromFile (char *fname, size_t *len, void **data); +int vo_setResultFromString (char *str, size_t *len, void **data); +int vo_setResultFromInt (int value, size_t *len, void **data); +int vo_setResultFromReal (float value, size_t *len, void **data); +int vo_appendResultFromString (char *str, size_t *len, void **data, + size_t *maxlen); + + + +/* Tasking parameter procedures. + */ +char **vo_paramInit (int argc, char *argv[], + char *opts, struct option long_opts[]); +int vo_paramNext (char *opts, struct option long_opts[], + int argc, char *argv[], char *optval, int *posindex); +void vo_paramFree (int argc, char *argv[]); diff --git a/vendor/voclient/voapps/voApps.i b/vendor/voclient/voapps/voApps.i new file mode 100644 index 00000000..b1ae3e7c --- /dev/null +++ b/vendor/voclient/voapps/voApps.i @@ -0,0 +1,90 @@ +/** + * VOAPPS.I -- SWIG Interface definition file. + * + * @file voApps.i + * @author Mike Fitzpatrick + * @date 6/03/12 + * + * @brief SWIG Interface definition file. + */ + +%module voapps +%{ + +/* SAMP messaging + */ +extern int vosamp (int argc, char **argv, size_t *len, void **result); + + +/* VOTable manipulation tasks. + */ +extern int votcnv (int argc, char **argv, size_t *len, void **result); +extern int votget (int argc, char **argv, size_t *len, void **result); +extern int votinfo (int argc, char **argv, size_t *len, void **result); +extern int votpos (int argc, char **argv, size_t *len, void **result); +extern int votsort (int argc, char **argv, size_t *len, void **result); +extern int votstat (int argc, char **argv, size_t *len, void **result); +/* +extern int votcat (int argc, char **argv, size_t *len, void **result); +extern int votjoin (int argc, char **argv, size_t *len, void **result); +extern int votsplit (int argc, char **argv, size_t *len, void **result); +*/ + + +/* VO Data Access tasks. + */ +extern int vodata (int argc, char **argv, size_t *len, void **result); +extern int voatlas (int argc, char **argv, size_t *len, void **result); + + +/* VO Registry query tasks. + */ +extern int voregistry (int argc, char **argv, size_t *len, void **result); + + +/* VO Name Resolution Tasks. + */ +extern int vosesame (int argc, char **argv, size_t *len, void **result); + +%} + + + + + +/* SAMP messaging + */ +extern int vosamp (int argc, char **argv, size_t *len, void **result); + + +/* VOTable manipulation tasks. + */ +extern int votcnv (int argc, char **argv, size_t *len, void **result); +extern int votget (int argc, char **argv, size_t *len, void **result); +extern int votinfo (int argc, char **argv, size_t *len, void **result); +extern int votpos (int argc, char **argv, size_t *len, void **result); +extern int votsort (int argc, char **argv, size_t *len, void **result); +extern int votstat (int argc, char **argv, size_t *len, void **result); +/* +extern int votcat (int argc, char **argv, size_t *len, void **result); +extern int votjoin (int argc, char **argv, size_t *len, void **result); +extern int votsplit (int argc, char **argv, size_t *len, void **result); +*/ + + +/* VO Data Access tasks. + */ +extern int vodata (int argc, char **argv, size_t *len, void **result); +extern int voatlas (int argc, char **argv, size_t *len, void **result); + + +/* VO Registry query tasks. + */ +extern int voregistry (int argc, char **argv, size_t *len, void **result); + + +/* VO Name Resolution Tasks. + */ +extern int vosesame (int argc, char **argv, size_t *len, void **result); + + diff --git a/vendor/voclient/voapps/voAppsP.h b/vendor/voclient/voapps/voAppsP.h new file mode 100644 index 00000000..268bf3d6 --- /dev/null +++ b/vendor/voclient/voapps/voAppsP.h @@ -0,0 +1,255 @@ +/** + * VOAPPSP.h -- Internal declarations for the VOClient Package applications. + * + * @file voAppsP.h + * @author Mike Fitzpatrick + * @date 6/03/11 + * + * @brief Internal declarations for the VOClient Package applications. + */ + + +#ifndef SZ_LINE +#define SZ_LINE 4096 +#endif +#ifndef SZ_URL +#define SZ_URL 1024 +#endif +#define DEF_SR 0.1 + + + +/* Local processing definitions. +*/ +#define MAX_DOWNLOADS 8 /* max downloads to run */ +#define MAX_THREADS 128 /* max threads to run */ +#define MAX_PROCS 64 /* max processes to run */ +#define DEF_DOWNLOADS 1 /* default no. downloads to run */ +#define DEF_NTHREADS 16 /* default num threads to run */ +#define DEF_NPROCS 10 /* default num processes to run */ +#define DEF_PGID 6200 /* default process group id */ + +#define SZ_TARGET 64 /* size of target name */ +#define DEF_SIZE 0.1 /* default search size (deg) */ + +#ifndef FAILED_ONLY +#define FAILED_ONLY 1 /* summarize only failed procs? */ +#endif + +/* NVO tool contexts. +*/ +#define CX_DATA 0001 /* DAL data access */ +#define CX_REGISTRY 0002 /* Registry resolution */ +#define CX_SESAME 0004 /* Object name resolution */ +#define CX_INVENTORY 0010 /* Data Inventory */ + +/* Output file formats. +*/ +#define F_ASCII 0001 /* ASCII table */ +#define F_RAW 0002 /* Raw VOTable */ +#define F_CSV 0004 /* Comma-separated-values */ +#define F_TSV 0010 /* Tab-separated-values */ +#define F_FITS 0020 /* FITS binary table */ +#define F_HTML 0040 /* HTML table */ +#define F_KML 0100 /* KML placemark table */ +#define F_XML 0200 /* XML document */ +#define F_META 0400 /* Metadata listing */ + +/* Service Types. +*/ +#define SVC_CONE 0001 /* Cone search service type */ +#define SVC_SIAP 0002 /* SIAP service */ +#define SVC_SSAP 0004 /* SSAP service */ +#define SVC_VIZIER 0010 /* Vizier TabularSkyService */ +#define SVC_SKYNODE 0020 /* Skynode */ +#define SVC_OTHER 0040 /* Other type of service */ + +/* Table pretty-print defs +*/ +#define PP_WIDTH 40 +#define PP_OFFSET 40 +#define PP_MAXCHARS 256 + +/* Registry query buffers +*/ +#define SZ_SQL_TERM 4096 +#define SZ_RESULT 40960 + +/* Range constants. +*/ +#define RANGE_ALL -1 +#define RANGE_NONE -2 +#define MAX_RANGES 1024 + +/* Data type codes. +*/ +#define DT_ANY 000 /* Any or not-specified */ +#define DT_CATALOG 001 /* Catalog data */ +#define DT_IMAGE 002 /* Image data */ +#define DT_SPECTRA 004 /* Spectral data */ +#define DT_RADIO 010 /* Radio data */ +#define DT_EVENT 020 /* Event-based data */ + + +/* Extraction types +*/ +#define EX_NONE 0000 /* No extractions */ +#define EX_ALL 0777 /* Generate all files */ +#define EX_BOTH 0001 /* Get positions and acrefs */ +#define EX_SAVE 0002 /* Save intermediate results */ +#define EX_COLLECT 0004 /* Collect intermediate results */ +#define EX_POS 0010 /* Get positions only */ +#define EX_ACREF 0020 /* Get acrefs only */ +#define EX_HTML 0040 /* Generate HTML table */ +#define EX_KML 0100 /* Generate KML file */ +#define EX_XML 0200 /* Generate XML document */ + +/* Error codes +*/ +#define E_NONE 0 /* No Error */ +#define E_NODATA 1 /* No Data Returned */ +#define E_REQFAIL 2 /* Request Failed */ +#define E_FILOPEN 3 /* File Open Error */ +#define E_VOCINIT 4 /* VOClient init failed */ + + + + +/* Utility macros. +*/ +#define VOT_NEXTARG(argc,argv,i) {if(i+1>=argc||(strlen(argv[i+1])>1&&argv[i+1][0]=='-'&&(!isdigit(argv[i+1][1])))){fprintf(stderr,"Error: Option '%s' requires an argument\n",argv[i]);break;}} + + +typedef int (*PFI)(); /* ptr to func returning an int */ + +#ifdef max +#undef max +#endif +#define max(a,b) (((a)>(b))?(a):(b)) + +#ifdef min +#undef min +#endif +#define min(a,b) (((a)<(b))?(a):(b)) + +#ifdef abs +#undef abs +#endif +#define abs(a) (((a)<0)?-(a):(a)) + + +/************************************************************************* +** Service calling params. +*/ +typedef struct { + /* Input params. */ + char service_url[SZ_LINE]; /* base service URL */ + char identifier[SZ_LINE]; /* service identifier */ + char name[SZ_LINE]; /* service short name */ + char oname[SZ_LINE]; /* object name */ + char title[SZ_LINE]; /* object name */ + char band[SZ_LINE]; /* BAND param (SSA) */ + char time[SZ_LINE]; /* TIME param (SSA) */ + int type; /* service type */ + int etype; /* extraction type */ + double ra; /* J2000 RA (dec. degrees) */ + double dec; /* J2000 Dec (dec. degrees) */ + float sr; /* search radius (degrees) */ + int fmt; /* output format */ + int index; /* output index */ + int svc_index; /* output service index */ + int obj_index; /* output object index */ +} svcParams; + + +/************************************************************************* +** Object/Position params. +*/ +typedef struct { + char name[SZ_FNAME]; /* object name */ + char id[SZ_FNAME]; /* object ID */ + double ra; /* Right Ascension (J200) */ + double dec; /* Declination (J200) */ + int index; /* list index */ + void *next; /* linked list pointer */ +} Object; + + +/************************************************************************* +** Range specification used for row/column selection. +*/ +typedef struct { + char rstring[SZ_FNAME]; /* range string */ + int ranges[MAX_RANGES]; /* expanded range array */ + int nvalues; /* num. values in range string */ +} Range; + +Range colRange; /* column selection range */ +Range rowRange; /* row selection range */ +Range fileRange; /* acref selection range */ + + +/************************************************************************* +** AccessReference or URL params. +*/ + +#define AC_PENDING 1 +#define AC_WORKING 2 +#define AC_COMPLETE 3 +#define AC_ERROR -1 + +typedef struct { + char url[SZ_LINE]; /* AcRef or URL */ + char fname[SZ_FNAME]; /* saved output file name */ + long nbytes; /* size of result */ + int status; /* error status */ + int index; /* list index */ + void *next; /* linked list pointer */ +} Acref; + + +/************************************************************************* +** Process call list for results summary. +*/ +typedef struct { + pid_t pid; /* process pid */ + Object *obj; /* Object */ + int status; /* return status */ + int count; /* query result count */ + char root[SZ_FNAME]; /* root file name */ + void *svc; /* back-pointer */ + void *next; /* linked list pointer */ +} Proc; + + +/************************************************************************* +** DAL Service params. Each service is comprised of a service URL that +** represents a specific type of DAL service. Once processed, the 'proc' +** list will contain summary information on each request and the 'acList' +** will contain all the images that need to be downloaded. Column and +** row selection are applied to each request, the download are done following +** the queries so we can parallelize them across all requested services. +*/ +typedef struct { + char name[SZ_FNAME]; /* service short name */ + char service_url[SZ_LINE]; /* base service URL */ + char identifier[SZ_LINE]; /* service identifier */ + char title[SZ_LINE]; /* service title string */ + int type; /* service type */ + int (*func)(svcParams *p); /* function to call */ + int cached; /* cached resource (NYI) */ + + int count; /* query result total count */ + int index; /* list index */ + + Proc *proc; /* process results list */ + int nfailed; /* no. of failed requests */ + int nnodata; /* no. of failed requests */ + + Acref *acList; /* acref list for service */ + int nrefs; /* no. of acrefs to download */ + + void *next; /* linked list pointer */ +} Service; + + diff --git a/vendor/voclient/voapps/voApps_spp.c b/vendor/voclient/voapps/voApps_spp.c new file mode 100644 index 00000000..21cf4145 --- /dev/null +++ b/vendor/voclient/voapps/voApps_spp.c @@ -0,0 +1,255 @@ +/** + * VOTAPP_SPP.C -- SPP Interface routines to applications code. + * + * @file votApp_spp.c + * @author Mike Fitzpatrick + * @date 6/03/11 + * + * @brief SPP Interface routines to applications code. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <unistd.h> +#include <ctype.h> +#include <errno.h> + +/* +#include "votParseP.h" +*/ +#include "votParse.h" + + +/* SPP Type definitions. +*/ +#define XCHAR short +#define PKCHAR char +#define XINT int +#define XEOS 0 + + +/* SPP Interface Definitions. + * + * SPP compilers on various platforms may append one or more trailing + * underscores to symbol names, we'll use macros for the interface names + * and use defines to see what the symbol name is. +*/ +#ifdef _NO_US_ + +#define VX_VODATA vxvoda +#define VX_VODIRECTORY vxvody +#define VX_VOSESAME vxvose + +#define VX_VOCOPY vxvocy +#define VX_VOGET vxvogt +#define VX_VOINFO vxvoio + +#else + +#define VX_VODATA vxvoda_ +#define VX_VODIRECTORY vxvody_ +#define VX_VOSESAME vxvose_ + +#define VX_VOCOPY vxvocy_ +#define VX_VOGET vxvogt_ +#define VX_VOINFO vxvoio_ + +#endif + +typedef void (*PFV)(); +typedef int (*PFI)(); + + + +/** + * Local interface declarations. + */ +static PKCHAR *spp2c (XCHAR *instr, int maxch); +static int spplen (XCHAR *str); +static void func_exec (PFV func, char *name, int *argc, XCHAR *firstArg, + va_list argp); + + + +/***************************************************************************** + * Application Interfaces + ****************************************************************************/ + +#define MAX_ARGS 64 + +void vodata (int argc, char **argv); +void voregistry (int argc, char **argv); +void vosesame (int argc, char **argv); + +void votcnv (int argc, char **argv); +void votget (int argc, char **argv); +void votinfo (int argc, char **argv); + +void voc_debug (void); + + + +/** + * FUNC_EXEC -- Execute a VOClient function from the SPP binding. + */ +static void +func_exec (PFV func, char *name, int *argc, XCHAR *firstArg, va_list argp) +{ + int i, _argc = *argc; + char *_argv[MAX_ARGS]; + XCHAR *arg; + + if (firstArg == NULL) /* must pass in at least one arg */ + return; + + + /* Process the argument list. + */ + _argc = *argc + 1; + _argv[0] = strdup (name); + _argv[1] = spp2c (firstArg, spplen (firstArg)); + + for (i=2; i < _argc && (arg=(XCHAR *)va_arg(argp,XCHAR *)) != NULL; i++) + if (arg) + _argv[i] = spp2c (arg, spplen (arg)); + + /* Debug output. + */ + if (access ("/tmp/VOC_DEBUG", F_OK) == 0) { + for (i=0; i < _argc; i++) + fprintf (stderr, "%s ", _argv[i]); + fprintf (stderr, "\n"); + } + + + (*func) (_argc, _argv); /* call the task */ + + for (i=0; i < *argc; i++) /* free the arg pointers */ + if (_argv[i]) + free ((char *) _argv[i]); + + return; +} + + +/**************************************************************************** + * Task wrappers + ****************************************************************************/ + +/** + * VX_VOCOPY -- Application interface to the VOCOPY task. + */ +void VX_VOCOPY (int *argc, XCHAR *firstArg, ...) +{ + va_list argp; + + va_start (argp, firstArg); + func_exec (votcnv, "votcopy", argc, firstArg, argp); + va_end (argp); +} + + +/** + * VX_VODATA -- Application interface to the VODATA task. + */ +void VX_VODATA (int *argc, XCHAR *firstArg, ...) +{ + va_list argp; + + va_start (argp, firstArg); + func_exec (vodata, "vodata", argc, firstArg, argp); + va_end (argp); +} + + +/** + * VX_VODIRECTORY -- Application interface to the VODIRECTORY task. + */ +void VX_VODIRECTORY (int *argc, XCHAR *firstArg, ...) +{ + va_list argp; + + va_start (argp, firstArg); + func_exec (voregistry, "vodirectory", argc, firstArg, argp); + va_end (argp); +} + + +/** + * VX_VOGET -- Application interface to the VOGET task. + */ +void VX_VOGET (int *argc, XCHAR *firstArg, ...) +{ + va_list argp; + + va_start (argp, firstArg); + func_exec (votget, "votget", argc, firstArg, argp); + va_end (argp); +} + +/** + * VX_VOINFO -- Application interface to the VOTINFO task. + */ +void VX_VOINFO (int *argc, XCHAR *firstArg, ...) +{ + va_list argp; + + va_start (argp, firstArg); + func_exec (votinfo, "votinfo", argc, firstArg, argp); + va_end (argp); +} + + +/** + * VX_VOSESAME -- Application interface to the VOSESAME task. + */ +void VX_VOSESAME (int *argc, XCHAR *firstArg, ...) +{ + va_list argp; + + va_start (argp, firstArg); + func_exec (vosesame, "vosesame", argc, firstArg, argp); + va_end (argp); +} + + + +/**************************************************************************** + * Private utility procedures + ****************************************************************************/ + +/** + * SPP2C -- Convert an SPP string to a host C string. + */ +static char * +spp2c (XCHAR *instr, int maxch) +{ + XCHAR *ip = instr; + char *outstr = (char *) calloc (1, maxch+1); + char *op = (char *) outstr; + int n = maxch; + + while ((*op++ = (char)*ip++) != (char)XEOS && --n >= 0) + ; + *--op = (char) XEOS; + + return (outstr); +} + + +/** + * SPPLEN -- Get the length of an SPP string. + */ +static int +spplen (XCHAR *str) +{ + int len = 0; + + for (len=0; str[len] != (XCHAR) XEOS; len++) + ; + return (len); +} + +void voc_debug () { int junk; junk = 1; } diff --git a/vendor/voclient/voapps/voatlas.c b/vendor/voclient/voapps/voatlas.c new file mode 100644 index 00000000..a72f4422 --- /dev/null +++ b/vendor/voclient/voapps/voatlas.c @@ -0,0 +1,660 @@ +/** + * VOATLAS -- Query the SkyView Image service for an all-sky image. + * + * Usage: voatlas [<opts>] <name> | <ra dec> + * + * Where + * -%%,--test run unit tests + * -h,--nelp this message + * -d,--debug enable debug messages + * -r,--return return result from method + * + * -b,--band <bpass> Bandpass + * -l,--list List available surveys for position + * -p,--survey <survey> Survey program name + * -g,--graphic Get a graphic image (i.e. JPEG) + * -n,--naxis <npix> Set returned image size + * + * -s,--size <size> Field size + * <size>s Field size (arcsec) + * <size>m Field size (arcmin) + * <size>d Field size (degrees, default) + * -F,--field <field> Resolve query field name + * -R,--ra <ra> Set query RA position + * -D,--dec <dec> Set query Dec position + * -P,--pos <ra,dec> Set query as a POS string + * -S,--samp Broadcast as SAMP message + * -o <name> Save image to named file + * + * <name> Target name to be resolved to position + * <ra> <dec> Position to query (dec. deg or Eq. sexagesimal) + * + * + * @file voatlas.c + * @author Mike Fitzpatrick + * @date 7/03/12 + * + * @brief Query the SkyView Image service for an all-sky image. + */ + + +#define _GNU_SOURCE /* for strcasestr() on linux */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include "VOClient.h" +#include "voApps.h" +#include "samp.h" + + +static double ra = 0.0; /* default values */ +static double dec = 0.0; +static double size = 0.25; + +static int debug = FALSE; /* debug output */ +static int do_samp = FALSE; /* broadcast SAMP msg? */ +static int graphic = FALSE; /* get graphics format? */ +static int list_surveys = FALSE; /* list results? */ +static int verbose = FALSE; /* verbose output? */ +static char *field = NULL; /* Input field name */ +static char *pos = NULL; /* Input position */ +static char *bpass = NULL; /* Bandpass */ + +static char svc_url[SZ_URL], survey[SZ_FNAME]; + + +static char *base_url = "http://skyview.gsfc.nasa.gov/cgi-bin/vo/sia.pl?"; + +static int voa_resolveField (char *field, double *ra, double *dec); +static int voa_resolvePos (char *pos, double *ra, double *dec); +static double voa_getSize (char *arg); +static int voa_callService (char *url, double ra, double dec, double size, + char *ofname, char *format, int maximages); + +extern double sexa (char *s); +extern char *strcasestr (); +extern int vot_atoi (char *v); +extern double vot_atof (char *v); + + +#ifdef USE_RESBUF +static char *resbuf; /* result buffer */ +#endif + + +/* Task specific option declarations. + */ +int voatlas (int argc, char **argv, size_t *len, void **result); + +static int do_return = 0; +static Task self = { "voatlas", voatlas, 0, 0, 0 }; +static char *opts = "%hF:R:D:P:b:dgs:o:Srlp:n:v"; +static struct option long_opts[] = { + { "field", 1, 0, 'F'}, /* query field name */ + { "ra", 1, 0, 'R'}, /* RA of position */ + { "dec", 1, 0, 'D'}, /* Dec of position */ + { "pos", 1, 0, 'P'}, /* POS position */ + { "graphics", 2, 0, 'g'}, /* graphics format? */ + { "band", 1, 0, 'b'}, /* bandpass */ + { "list", 2, 0, 'l'}, /* list surveys */ + { "survey", 1, 0, 'p'}, /* survey name */ + { "naxis", 1, 0, 'n'}, /* image size */ + { "size", 1, 0, 's'}, /* query size */ + { "output", 1, 0, 'o'}, /* set output name */ + { "samp", 2, 0, 'S'}, /* broadcast SAMP */ + { "verbose", 2, 0, 'v'}, /* required */ + { "help", 2, 0, 'h'}, /* required */ + { "debug", 2, 0, 'd'}, /* required (debug) */ + { "test", 2, 0, '%'}, /* required */ + { "return", 1, 0, 'r'}, /* required */ + { NULL, 0, 0, 0 } +}; + +static void Usage (void); +static void Tests (char *input); + + + +/** + * Application entry point. + */ +int +voatlas (int argc, char **argv, size_t *reslen, void **result) +{ + char **pargv, optval[SZ_FNAME], ch; + char *iname = NULL, *oname = NULL, *dlname = NULL; + char tmp[SZ_FNAME], buf[SZ_FNAME]; + int i=1, status = OK, apos = 0, samp = -1, naxis = 512; + + + /* Initialize. + */ + memset (buf, 0, SZ_FNAME); + memset (tmp, 0, SZ_FNAME); + memset (survey, 0, SZ_FNAME); + memset (svc_url, 0, SZ_URL); + + *reslen = 0; + *result = NULL; + + + /* Parse the argument list. + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + while ((ch = vo_paramNext (opts,long_opts,argc,pargv,optval,&apos)) != 0) { + i++; + if (ch > 0) { + switch (ch) { + case '%': Tests (optval); return (self.nfail); + case 'h': Usage (); return (OK); + case 'd': debug++; break; + case 'r': do_return++; break; + + case 'b': bpass = strdup (optval); i++; break; + case 'g': graphic++; break; + case 'l': list_surveys++; + strcpy (survey, "list"); break; + case 'p': strcpy (survey, optval); i++; break; + case 'n': naxis = vot_atoi (optval); i++; break; + + case 'F': field = strdup (optval); i++; break; + case 'R': if (strchr (optval, (int)':')) + ra = (15. * (double) sexa (optval)); + else + ra = (double) vot_atof (optval); + i++; + break; + case 'D': if (strchr (optval, (int)':')) + dec = (double) sexa (optval); + else + dec = (double) vot_atof (optval); + i++; + break; + case 'P': sscanf (optval, "%lf,%lf", &ra, &dec); + i++; + break; + + case 's': size = voa_getSize(optval); i++; break; + case 'o': oname = strdup (optval); i++; break; + + case 'S': do_samp = 1; break; + case 'v': verbose = 1; break; + + default: + fprintf (stderr, "Invalid argument '%c'\n", ch); + return (ERR); + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + if (i == (argc-2)) { + sprintf (buf, "%s %s", optval, argv[i+1]); + pos = strdup (buf); + sscanf (pos, "%lf %lf", &ra, &dec); + } else + field = strdup (optval); + break; + } + } + + + /* Sanity checks. + */ + if (!field && !pos && (ra == 0.0 && dec == 0.0)) { + fprintf (stderr, "Error: no field/position specified.\n"); + return (ERR); + } + + if (!survey[0]) { + /* No survey specified so go by the bandpass. + */ + if (!bpass) + strcpy (survey, "dss2b"); + else { + if (strncasecmp (bpass, "optical", 3) == 0) + strcpy (survey, "dss"); + else if (strncasecmp (bpass, "infrared", 3) == 0 || + strncasecmp (bpass, "ir", 2) == 0) + strcpy (survey, "2massk"); + else if (strncasecmp (bpass, "x-ray", 1) == 0) + strcpy (survey, "pspc2int"); + else if (strncasecmp (bpass, "euv", 3) == 0) + strcpy (survey, "euve83"); + else if (strncasecmp (bpass, "gamma-ray", 5) == 0) + strcpy (survey, "egret1000"); + else if (strncasecmp (bpass, "radio", 3) == 0) + strcpy (survey, "4850mhz"); + } + } else if (strcasecmp (survey, "list") == 0) { + list_surveys = 1; + memset (survey, 0, SZ_FNAME); + } + + + /* Setup the output name. + */ + if (oname) { + dlname = oname; /* output name specified */ + } else if (do_samp) { + strcpy (tmp, "/tmp/voatlasXXXXXX"); /* temp download name */ + mktemp (tmp); + dlname = tmp; + } else { + if (field) + sprintf (buf, "%s.%s", field, (graphic ? "jpg" : "fits")); + + else if (pos) { + char *ip, *op; + + memset (buf, 0, SZ_FNAME); + for (op=buf, ip=pos; *ip; ip++) + *op++ = (*ip == ' ' ? '_' : *ip); + strcat (buf, "."); + strcat (buf, (graphic ? "jpg" : "fits")); + + } else if (list_surveys) { + if (verbose) + fprintf (stderr, + "Warning: no field/position specified, using (0.,0.).\n"); + + } else { + fprintf (stderr, "Error: no output name specified.\n"); + status = ERR; + goto done_; + } + dlname = oname = strdup (buf); + } + + + if (debug) { + fprintf (stderr, "field='%s' pos='%s' ra=%g dec=%g\n", + field, pos, ra, dec); + fprintf (stderr, "bpass='%s' survey='%s'\n", bpass, survey); + fprintf (stderr, "oname='%s'\n", oname); + } + + /* 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.voatlas") == ERR) + return (ERR); + + /* Sanity checks + */ + if (iname == NULL) iname = strdup ("stdin"); + if (oname == NULL) oname = strdup ("stdout"); + if (strcmp (iname, "-") == 0) { free (iname), iname = strdup ("stdin"); } + if (strcmp (oname, "-") == 0) { free (oname), oname = strdup ("stdout"); } + + if (field && pos) { + fprintf (stderr, + "Error: only one of 'field' or 'pos' may be specified.\n"); + status = ERR; + goto done_; + } else if (field) { + if (voa_resolveField (field, &ra, &dec) == OK) { + fprintf (stderr, "Error: cannot resolve object '%s'\n", field); + status = ERR; + goto done_; + } + } else if (pos) { + if (voa_resolvePos (pos, &ra, &dec) != OK) { + fprintf (stderr, "Error: cannot convert position '%s'\n", pos); + status = ERR; + goto done_; + } + } + + + /* Form the service URL. + */ + memset (svc_url, 0, SZ_URL); + sprintf (svc_url, "%snaxis=%d&", base_url, naxis); + if (survey[0]) { + strcat (svc_url, "survey="); + strcat (svc_url, survey); + strcat (svc_url, "&"); + } + if (debug) + fprintf (stderr, "ra = %g dec = %g\nurl='%s'\n", ra, dec, svc_url); + + + /* Call the SkyView SIA service. + */ + if (voa_callService (svc_url, ra, dec, size, dlname, + (graphic ? "jpeg" : "fits"), 1) == ERR) { + fprintf (stderr, "Error: cannot contact SkyView service\n"); + status = ERR; + goto done_; + } + + /* Broadcast the image as a message if requested. + */ + if (do_samp) { + if ((samp = sampInit ("voatlas", "VOClient Task")) >= 0) { + char url[SZ_LINE], cwd[SZ_LINE]; + + samp_setSyncMode (samp); /* use asynchronous mode */ + sampStartup (samp); /* register w/ Hub */ + + memset (url, 0, SZ_LINE); + memset (cwd, 0, SZ_LINE); + getcwd (cwd, SZ_LINE); + if (tmp[0]) + sprintf (url, "file://%s", dlname); + else + sprintf (url, "file://%s/%s", cwd, oname); + + if (verbose) + printf ("Displaying image %s ...\n", url); + (void) samp_imageLoadFITS (samp, "all", url, "", field); + + if (tmp[0]) + unlink (dlname); + sampShutdown (samp); + } + } + + + /* See if we're returning the image. + */ + if (do_return) { + vo_setResultFromFile (dlname, reslen, result); + unlink (dlname); + } + + + /* Clean up and shutdown. + */ +done_: + if (pos) free (pos); + if (field) free (field); + if (iname) free (iname); + if (oname) free (oname); + + voc_closeVOClient (1); + vo_paramFree (argc, pargv); + + sleep (2); /* FIXME -- SkyView seems to have a reset issue... */ + + return (status); +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "voatlas [<opts>] [<field> | <pos>]\n\n" + " where\n" + " -%%,--test run unit test\n" + " -d,--debug enable debugging\n" + " -h,--nelp this messag\n" + " -r,--return return result from metho\n" + "\n" + " -b,--band <bpass> Bandpas\n" + " -p,--survey <survey> Survey program nam\n" + " -g,--graphic Get a graphic image (i.e. JPEG\n" + " -n,--naxis <npix> Set returned image size\n" + "\n" + " -s,--size <size> Field siz\n" + " <size>s Field size (arcsec\n" + " <size>m Field size (arcmin\n" + " <size>d Field size (degrees, default\n" + " -F,--field <field> Resolve query field nam\n" + " -R,--ra <ra> Set query RA positio\n" + " -D,--dec <dec> Set query Dec positio\n" + " -P,--pos <ra,dec> Set query as a POS strin\n" + " -S,--samp Broadcast as SAMP messag\n" + " -v,--verbose Verbose output\n" + " -o <name> Save image to named fil\n" + "\n" + " <name> Target name to be resolved\n" + " <ra> <dec> Position to query\n" + "\n" + "Examples:\n\n" + " 1) Display an image of M83 on Aladin using SAMP\n\n" + " %% voatlas --samp m83\n" + "\n" + " 2) Get a 256x256 JPEG image of the Sombrero galaxy\n\n" + " %% voatlas -o gal.jpg -n 256 --graphic sombrero\n" + "\n" + " 3) Get a 20 arcmin Wise 2.2micron survey image of m101\n\n" + " %% voatlas -s 20m --survey=wise22 m101\n" + "\n" + " 4) Get a radio image of 3c273, image will be '3c273.fits'\n\n" + " %% voatlas --band=radio 3c273\n" + "\n" + " 5) List (verbose) the survey images available for ngc1234\n\n" + " %% voatlas --survey=list -v ngc1234\n" + "\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + vo_taskTest (task, "--help", NULL); + vo_taskTest (task, "-S", "m83", NULL); // Ex 1 + vo_taskTest (task, "--samp", "m83", NULL); + + vo_taskTest (task, "-o", "gal.jpg", "-n", "256", // Ex 2 + "--graphic", "sombrero", NULL); + + vo_taskTest (task, "-s", "20m", "--survey=wise22", "m101", NULL); // Ex 3 + + vo_taskTest (task, "--band=radio", "3c273", NULL); // Ex 4 + + vo_taskTest (task, "--survey=list", "-v", "ngc1234", NULL); // Ex 5 + + vo_taskTest (task, "m51", NULL); + vo_taskTest (task, "-o", "m51.fits", "m51", NULL); + vo_taskTest (task, "--ra=202.47", "--dec=47.195", "--samp", NULL); + + /* Clean up any files we created. + */ + if (access ("m51.fits", F_OK) == 0) unlink ("m51.fits"); + if (access ("m101.fits", F_OK) == 0) unlink ("m101.fits"); + if (access ("3c273.fits", F_OK) == 0) unlink ("3c273.fits"); + if (access ("gal.jpg", F_OK) == 0) unlink ("gal.jpg"); + + vo_taskTestReport (self); +} + + + +/** + * Simple test routine to call a Siap search service and summarize results. + */ +static int +voa_callService (char *svc_url, double ra, double dec, double size, + char *ofname, char *format, int maximages) +{ + char *acref = NULL, *fmt = NULL, *program = NULL; + double dra, ddec; + int i, nrec = 0, recnum = 0; + FILE *fd = (FILE *) NULL; + + + DAL siap; /* DAL Connection */ + Query query; /* query handle */ + QResponse qr; /* query response handle */ + QRecord rec; /* result record handle */ + QRAttribute v; /* dataset attribute */ + + + /* Get a new connection to the named service. + */ + siap = voc_openSiapConnection (svc_url); /* open a connection */ + + /* Form a query. Here we'll use the one search size we're given for + * both the RA,DEC sizes, and specify a null format. + */ + query = voc_getSiapQuery (siap, ra, dec, size, size, + (list_surveys ? NULL : (graphic ? "image/jpeg" : "image/fits"))); + + + if (VOAPP_DEBUG) { + fprintf (stderr, "Executing Query:\n %s\n\n", + voc_getQueryString (query, SIAP_CONN, 0)); + } + + + /* Execute the query. + */ + qr = voc_executeQuery (query); /* execute the query */ + if ((nrec = voc_getRecordCount (qr)) <= 0) + return (ERR); + + if (do_return && list_surveys) + fd = fopen (ofname, "w+"); + else + fd = stdout; + + + /* Download the first 'maximages' images. + */ + for (i=0; i < nrec && i < nrec; i++) { + rec = voc_getRecord (qr, i); /* get a row in the table */ + + v = voc_getAttribute (rec, "Format"); /* get the right format */ + if (!(fmt = voc_stringValue(v)) || strcasestr (fmt, format) == NULL) + if (!list_surveys) + continue; + + v = voc_getAttribute (rec, "Title"); /* get the survey */ + program = voc_stringValue(v); + if (list_surveys) { + v = voc_getAttribute (rec, "Ra"); dra = voc_floatValue (v); + v = voc_getAttribute (rec, "Dec"); ddec = voc_floatValue (v); + if (verbose) + fprintf (fd, "%3d %12.12s %g %g %s\n", + (i+1), program, dra, ddec, fmt); + else + fprintf (fd, "%3d %12.12s %s\n", (i+1), program, fmt); + + } else if (program) { + int plen = strlen (program); + int slen = strlen (survey); + + if (strncasecmp (program, survey, min(plen,slen)) == 0) { + if ((v = voc_getAttribute (rec, "AccessReference"))) { + acref = voc_stringValue (v); + if (verbose) { + printf ("Downloading %d of %d: '%s' ....", + i, nrec, ofname); + fflush (stdout); + } + if ( voc_getDataset (rec, acref, ofname) != OK ) { + if (verbose) + printf ("error downloading file\n"); + return (ERR); + } + if (verbose) + printf ("done\n"); + + if ( ++recnum >= maximages ) + break; + } + } + } + } + + if (fd != stdout) + fclose (fd); + + voc_closeConnection (siap); /* close the siap connection */ + return (OK); +} + + +/** + * VOA_RESOLVEPOS -- Resolve a position string to decimal degrees. + */ +static int +voa_resolvePos (char *pos, double *ra, double *dec) +{ + char *ip = NULL, *s1 = NULL, *s2 = NULL; + + + if ( (ip = strchr (pos, (int)' '))) { + *ip = '\0'; + s1 = pos; + s2 = ip + 1; + + if (strchr (s1, (int)':')) + *ra = (15. * (double) sexa (s1)); + else + *ra = (double) vot_atof (s1); + *dec = (strchr (s2,(int)':') ? + (double) sexa (s2) : (double) vot_atof (s2)); + + return (OK); + } else + return (ERR); + +} + + +/** + * VOA_RESOLVEFIELD -- Resolve an object field name to a position in decimal + * degrees. + */ +static int +voa_resolveField (char *field, double *ra, double *dec) +{ + Sesame sr; + extern char *vo_urlEncode(); + + + if ((sr = voc_nameResolver (vo_urlEncode (field))) != 0) { + *ra = (double) voc_resolverRA (sr); + *dec = (double) voc_resolverDEC (sr); + } + return ((sr > 0) ? OK : ERR); +} + + +/** + * VOA_GETSIZE -- Convert an argument size spec into a decimal degree value. + */ +static double +voa_getSize (char *arg) +{ + int len = strlen (arg); + int unit = 'd'; + double size = (double) 0.0; + + + if (isalpha ((int) arg[len-1]) && arg[len-1] != '.') { + unit = tolower (arg[len-1]); + if (strchr ("mdsMDS", unit) == NULL) { + fprintf (stderr, "Error: Invalid size unit '%c'\n", unit); + return (size); + } + arg[len-1] = '\0'; + } + + /* Convert to decimal degrees for the query. + */ + switch (unit) { + case 'd': return ( vot_atof (arg) ); + case 'm': return ( vot_atof (arg) / 60. ); + case 's': return ( vot_atof (arg) / 3600. ); + } + + return ((double) 0.0); +} diff --git a/vendor/voclient/voapps/vocatalog.c b/vendor/voclient/voapps/vocatalog.c new file mode 100644 index 00000000..9e0b303b --- /dev/null +++ b/vendor/voclient/voapps/vocatalog.c @@ -0,0 +1,155 @@ +/** + * VOCATALOG -- Query all VO Catalog services + * + * Usage: + * vocatalog [<opts>] [ <object> | <ra> <dec> ] [ <size> ] + * + * @file vocatalog.c + * @author Mike Fitzpatrick + * @date 2/03/13 + * + * @brief Query all VO Image services. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "votParse.h" /* keep these in order! */ +#include "voApps.h" + + +/* Task specific option declarations. Task options are declared using the + * getopt_long(3) syntax. + */ +int vodata (int argc, char **argv, size_t *len, void **result); +int vocatalog (int argc, char **argv, size_t *len, void **result); + +static Task self = { "vocatalog", vocatalog, 0, 0, 0 }; + +extern void vot_setArg (char **argv, int *argc, char *value); + +static void Usage (void); +static void Tests (char *input); + + +/** + * Application entry point. All VOApps tasks MUST contain this + * method signature. + */ +int +vocatalog (int argc, char **argv, size_t *reslen, void **result) +{ + char *pargv[argc+2]; + int i, narg = 0, status = OK; + + + /* Initialize result object whether we return an object or not. + */ + *reslen = 0; + *result = NULL; + + /* Do a quick check of the args so we can provide a task-local + * help and test option. Otherwise, we simply pass thru all the + * args to VODATA for processing. + */ + if (strncmp (argv[1],"-h",2) == 0 || strncmp (argv[1],"--help",6) == 0) { + Usage (); return (OK); + } + if (strncmp (argv[1],"-%",2) == 0 || strncmp (argv[1],"--test",6) == 0) { + Tests (NULL); return (self.nfail); + } + + /* Initialize the new argument vector. + */ + vot_setArg (pargv, &narg, argv[0]); + vot_setArg (pargv, &narg, "--type=catalog"); + for (i=1; i < argc; i++) + vot_setArg (pargv, &narg, argv[i]); + + + /** + * The VODATA task does all the real work, we effectively just set the + * "-t catalog" option to force the service type as a logical naming + * convenience for the user. Note that return parameters are handled + * by vodata as well so there is no processing required here. + */ + status = vodata (narg, pargv, reslen, result); + + + /* Clean up. Rememebr to free whatever pointers were created when + * parsing arguments. + */ + for (i=0; i < (argc + 2); i++) + free ((void *) pargv[i]); + + return (status); +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "vocatalog [<opts>] votable.xml\n\n" + " where\n" + " -%%,--test run unit tests\n" + " -h,--help this message\n" + "\n" + " <opts> includes all valid VODATA options\n" + "\n" + " Examples:\n\n" + " 1) Query the GSC 2.3 catalog for stars a) within the 0.1 \n" + " degree default search size around NGC 1234: b) around all\n" + " positions contained in file 'pos.txt': c) for the list \n" + " of objects given on the command line: d) query a list of\n" + " services for a list of positions: e) print a count of \n" + " results that would be returned from 3 services for each\n" + " position in a file:\n\n" + " %% vocatalog gsc2.3 ngc1234 (a)\n" + " %% vocatalog gsc2.3 pos.txt (b)\n" + " %% vocatalog gsc2.3 m31,m51,m93 (c)\n" + " %% vocatalog svcs.txt pos.txt (d)\n" + " %% vocatalog hst,chandra,gsc2.3 pos.txt (e)\n" + "\n" + " 2) Print a count of X-ray catalog data around Abell2712:\n\n" + " %% vocatalog -c -b x-ray any abell2712\n" + " %% vocatalog --count -b x-ray any abell2712\n" + "\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + vo_taskTest (task, "--help", NULL); + + vo_taskTestFile ("m31\nm51\nm93\n", "pos.txt"); + vo_taskTestFile ("hst\nchandra\ngsc2.3\n", "svcs.txt"); + + vo_taskTest (task, "gsc2.3", "ngc1234", NULL); // Ex 1 + 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", "-b", "x-ray", "any", "abell2712", NULL); // Ex 2 + vo_taskTest (task, "--count", "-b", "x-ray", "any", "abell2712", NULL); + + + if (access ("pos.txt", F_OK) == 0) unlink ("pos.txt"); + if (access ("svcs.txt", F_OK) == 0) unlink ("svcs.txt"); + + vo_taskTestReport (self); +} diff --git a/vendor/voclient/voapps/voclient_test b/vendor/voclient/voapps/voclient_test new file mode 100755 index 00000000..7f056f9b --- /dev/null +++ b/vendor/voclient/voapps/voclient_test @@ -0,0 +1,29 @@ +#!/bin/csh -f + +set nf = 0 + +date + +voatlas -% ; set nf = `expr $nf + $status` +vocatalog -% ; set nf = `expr $nf + $status` +vodata -% ; set nf = `expr $nf + $status` +voimage -% ; set nf = `expr $nf + $status` +voiminfo -% ; set nf = `expr $nf + $status` +voregistry -% ; set nf = `expr $nf + $status` +vosamp -% ; set nf = `expr $nf + $status` +vosesame -% ; set nf = `expr $nf + $status` +vosloanspec -% ; set nf = `expr $nf + $status` +vospectra -% ; set nf = `expr $nf + $status` +votcnv -% data/ned.xml ; set nf = `expr $nf + $status` +votget -% data/sia.xml ; set nf = `expr $nf + $status` +votinfo -% data/ned.xml ; set nf = `expr $nf + $status` +votopic -% ; set nf = `expr $nf + $status` +votpos -% data/ned.xml ; set nf = `expr $nf + $status` +votsort -% data/sort.xml ; set nf = `expr $nf + $status` + +echo "" +echo "" +echo "NFailed = $nf" +echo "" + +date 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); +} + diff --git a/vendor/voclient/voapps/vodata.c.bak b/vendor/voclient/voapps/vodata.c.bak new file mode 100644 index 00000000..15f82343 --- /dev/null +++ b/vendor/voclient/voapps/vodata.c.bak @@ -0,0 +1,2256 @@ +/************************************************************************ +** VODATA -- Query a VO Data service (Cone or SIAP) +** +** Usage: vodata [-<flags>] [<service>] [object|file|position] +** +** M. Fitzpatrick, NOAO, July 2007 +*/ + +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.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 *next, char **argv, int argc); +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 Task self = { "vodata", vodata, 0, 0, 0 }; + +static void Usage (void); +static void Tests (char *input); + + +/* For getopt_long() option parsing. +*/ +int opt_index; +#ifdef USE_GETOPT +static char *opt_string = ""; /* not used */ +static struct option long_options[] = { /* not used */ + { NULL, 0, 0, 0 } +}; +#endif + + + + +/************************************************************************ +** Program main() +*/ +int +vodata (int argc, char *argv[], size_t *reslen, void **result) +{ + register int i, j, len, ch; + char *eval, *argfile, *next_arg, posn[SZ_LINE]; + + + /* 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"); + } + + for (i=1; i < argc; i++) { + + if (argv[i][0] == '-') { + len = strlen (argv[i]); + for (j=1; j < len; j++) { + + if (argv[i][j] == '-') { + ch = vot_setArgWord (&argv[i][j+1], argv[i+1], argv, argc); + j += len - 1; + if (ch < 0) /* handled in vot_setArgWord() */ + continue; + } else + ch = argv[i][j]; + + switch (ch) { + case 'h': /* help */ + Usage (); + voc_closeVOClient (0); + return (OK); + + case '%': /* unit tests */ + voc_closeVOClient (0); + Tests (NULL); + return (self.nfail); + + case '1': /* one-file output */ + extract |= EX_COLLECT; + break; + 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 = argv[++i]; + 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 (argv[i+1][0] == '/' || isdigit(argv[i+1][0])) + d2_band = argv[++i]; + else + if (strncasecmp (argv[++i], "any", 3) != 0) + bpass = argv[i]; + break; + case 'c': + count++; + count_only = TRUE; + break; + + case 'e': /* extract pos/acrefs? */ + if (strncmp (argv[i+1], "pos", 3) == 0) + extract |= EX_POS, i++; + else if (strncmp (argv[i+1], "url", 3) == 0) + extract |= EX_ACREF, i++; + else if (strncmp (argv[i+1], "head", 4) == 0) + extract |= EX_HTML, i++; + else if (strncmp (argv[i+1], "kml", 3) == 0) + extract |= EX_KML, i++; + else if (strncmp (argv[i+1], "xml", 3) == 0) + extract |= EX_XML, i++; + else + extract = EX_ALL; + 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 = 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 = 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"); + exit (1); + } 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(argv[i+1]) || isDecimal(argv[i+1])) { + sprintf (posn, "%s %s", argv[i+1], argv[i+2]); + vot_parseObjectList (posn, TRUE); + i += 2; + } else if (inventory) { + vot_parseObjectList (argv[++i], TRUE); + sources = argv[i]; + if (debug) + fprintf (stderr, + "setting pos sources='%s'\n", sources); + } else + vot_parseObjectList (argv[++i], 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 = argv[++i]), dalOnly); + if (debug) + fprintf (stderr, "setting resources = '%s'\n", + resources); + } else { + vot_parseServiceList ((resources = 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 (argv[++i], "any", 3) != 0) + typestr = argv[i]; + break; + + case 'u': /* forced url download */ + url_proc++; + break; + + case 'v': /* verbose flag */ + verbose = min(3,(verbose+1)); + break; + } + + + /* If we have a 'ch' we used a long flag, break now. + */ + if (ch > 0) + break; + } + + } 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 = 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 = argv[++i]; + break; + case 'v': + dverbose++; + break; + } + } + + } 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; + + 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; + } + + + 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); + */ + + 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 *next, char **argv, int argc) +{ +fprintf (stderr, "setArg: arg = '%s'\n", arg); + + if (arg[0] == '-') { + fprintf (stderr, "Invalid argument string '--'\n"); + exit(1); + + /* '--' only FLAGS */ + } else if (strncmp (arg, "bandpass", 8) == 0) { + bpass = vot_requiredArg (arg); + + } else if (strncmp (arg, "cols", 4) == 0) { + cols = vot_requiredArg (arg); + + } else if (strncmp (arg, "delim", 5) == 0) { + delim = vot_requiredArg (arg); + 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 (arg[7] != '=') /* just "--extract" */ + extract |= EX_ALL; + + else { + (void) vot_requiredArg (arg); + switch (arg[8]) { + 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 (arg); + + } else if (strncmp (arg, "get", 3) == 0) { + char *ip = vot_optionalArg (arg); + + 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; + } + + } else if (strncmp (arg, "hskip", 5) == 0) { + table_hskip = vot_atoi ( vot_requiredArg (arg) ); + + } else if (strncmp (arg, "kml", 3) == 0) { + + (void) vot_requiredArg (arg); + switch (arg[3]) { + case 'm': /* max placemarks --kmlmax=N */ + kml_max = vot_atoi(&arg[7]); + break; + case 'g': /* grouping --kmlgroup=type */ + switch (arg[9]) { + 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(&arg[10]); + 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 (arg, "kmlgroup", 8) == 0) + extract |= EX_KML; + + } else if (strncmp (arg, "max", 3) == 0) { + char *ip = vot_requiredArg (arg); + + 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) { + table_nlines = vot_atoi ( vot_requiredArg (arg) ); + + } else if (strncmp (arg, "object", 6) == 0) { + char *ip = vot_requiredArg (arg); + + 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++; + + } 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); + } + + } else if (strncmp (arg, "pos", 3) == 0) { + char posn[SZ_LINE]; + char *ip = vot_requiredArg (arg); + + 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 (arg, (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++; + + } else if (strncmp (arg, "proxy", 5) == 0) { + proxy++; + + } 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 (arg); + 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; + } + + + } else if (strncmp (arg, "svc", 3) == 0) { + char *ip = vot_requiredArg (arg); + + 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++; + + } else if (strncmp (arg, "type", 4) == 0) { + typestr = vot_requiredArg (arg); + + } else if (strncmp (arg, "verbose", 7) == 0) { + verbose = min (3, vot_atoi ( vot_optionalArg (arg)) );; + + } else if (strncmp (arg, "vverbose", 8) == 0) { + verbose = 3; + + + } else if (strncmp (arg, "web", 3) == 0) { + char *val = vot_requiredArg (arg); + switch (val[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 */ + } + + /* DAL2 OPTION FLAGS */ + } else if (strncmp (arg, "band", 4) == 0) { + d2_band = vot_requiredArg (arg); + } else if (strncmp (arg, "time", 4) == 0) { + d2_time = vot_requiredArg (arg); + } else if (strncmp (arg, "format", 6) == 0) { + d2_format = vot_requiredArg (arg); + } else if (strncmp (arg, "version", 7) == 0) { + d2_version = vot_requiredArg (arg); + + /* MISC OPTION FLAGS */ + } else if (strncmp (arg, "all", 3) == 0) { return ('a'); + } else if (strncmp (arg, "count", 5) == 0) { return ('c'); + } else if (strncmp (arg, "force", 5) == 0) { return ('f'); +/* } else if (strncmp (arg, "get", 3) == 0) { return ('g'); */ + } else if (strncmp (arg, "help", 4) == 0) { return ('h'); + } else if (strncmp (arg, "inventory",9) == 0) { return ('I'); + } else if (strncmp (arg, "nosave", 6) == 0) { return ('n'); + } else if (strncmp (arg, "one", 3) == 0) { return ('1'); + } else if (strncmp (arg, "quiet", 5) == 0) { return ('q'); + } else if (strncmp (arg, "url", 3) == 0) { return ('u'); + + /* OUTPUT FORMAT FLAGS */ + } else if (strncmp (arg, "ascii", 5) == 0) { return ('A'); + } else if (strncmp (arg, "csv", 3) == 0) { return ('C'); + } else if (strncmp (arg, "tsv", 3) == 0) { return ('T'); + } else if (strncmp (arg, "fits", 4) == 0) { return ('F'); + } else if (strncmp (arg, "kml", 3) == 0) { return ('K'); + } else if (strncmp (arg, "html", 4) == 0) { return ('H'); + } else if (strncmp (arg, "raw", 3) == 0) { return ('R'); + } else if (strncmp (arg, "xml", 3) == 0) { return ('X'); + } else if (strncmp (arg, "votable", 7) == 0) { return ('V'); + + } + +fprintf (stderr, "setArg: ARG_DONE\n"); + return (ARG_DONE); +} + + +static char * +vot_requiredArg (char *arg) +{ + char *ip = strchr (arg, (int)'='); + + if (!ip) { + fprintf (stderr, "ERROR: Missing '--%s' argument.\n", arg); + exit (1); + } + + return (++ip); +} + +static char * +vot_optionalArg (char *arg) +{ + char *ip = strchr (arg, (int)'='); + + if (!ip) + return (NULL); + else + return (++ip); +} + + + + +/************************************************************************ +** 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. + */ + 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 (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, -vv 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 table output (.txt extension)\n"); + printf (" -C CSV table output (.csv extension)\n"); + printf (" -H HTML table output (.html extension)\n"); +#ifdef VO_INVENTORY + printf (" -I Output results from the Inventory Service\n"); +#endif + printf (" -K KML output (.kml extension)\n"); + printf (" -R Raw (VOTable) output (.xml extension)\n"); + printf (" -V VOTable output (.xml extension)\n"); + printf (" -T Tab-separated table output (.tsv extension)\n"); + printf (" -O <root> Set the root part of output name\n"); + printf ("\n"); + printf (" -e 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 No-save results, print a count only\n"); + printf (" -q 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\ + Or to get a count of all catalog data for that position:\n\ +\n\ + %% vodata -I 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); +} + diff --git a/vendor/voclient/voapps/voimage.c b/vendor/voclient/voapps/voimage.c new file mode 100644 index 00000000..4bb1e520 --- /dev/null +++ b/vendor/voclient/voapps/voimage.c @@ -0,0 +1,133 @@ +/** + * VOIMAGE -- Query all VO Image services + * + * Usage: + * voimage [<opts>] [ <object> | <ra> <dec> ] [ <size> ] + * + * @file voimage.c + * @author Mike Fitzpatrick + * @date 2/03/13 + * + * @brief Query all VO Image services. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "votParse.h" /* keep these in order! */ +#include "voApps.h" + + +/* Task specific option declarations. Task options are declared using the + * getopt_long(3) syntax. + */ +int vodata (int argc, char **argv, size_t *len, void **result); +int voimage (int argc, char **argv, size_t *len, void **result); + +static Task self = { "voimage", voimage, 0, 0, 0 }; + +extern void vot_setArg (char **argv, int *argc, char *value); + +static void Usage (void); +static void Tests (char *input); + + +/** + * Application entry point. All VOApps tasks MUST contain this + * method signature. + */ +int +voimage (int argc, char **argv, size_t *reslen, void **result) +{ + char *pargv[argc+2]; + int i, narg = 0, status = OK; + + + /* Initialize result object whether we return an object or not. + */ + *reslen = 0; + *result = NULL; + + /* Do a quick check of the args so we can provide a task-local + * help and test option. Otherwise, we simply pass thru all the + * args to VODATA for processing. + */ + if (strncmp (argv[1],"-h",2) == 0 || strncmp (argv[1],"--help",6) == 0) { + Usage (); return (OK); + } + if (strncmp (argv[1],"-%",2) == 0 || strncmp (argv[1],"--test",6) == 0) { + Tests (NULL); return (self.nfail); + } + + /* Initialize the new argument vector. + */ + vot_setArg (pargv, &narg, argv[0]); + vot_setArg (pargv, &narg, "--type=image"); + for (i=1; i < argc; i++) + vot_setArg (pargv, &narg, argv[i]); + + + /** + * The VODATA task does all the real work, we effectively just set the + * "-t image" option to force the service type as a logical naming + * convenience for the user. Note that return parameters are handled + * by vodata as well so there is no processing required here. + */ + status = vodata (narg, pargv, reslen, result); + + + /* Clean up. Rememebr to free whatever pointers were created when + * parsing arguments. + */ + for (i=0; i < (argc + 2); i++) + free ((void *) pargv[i]); + + return (status); +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "voimage [<opts>] votable.xml\n\n" + " where\n" + " -%%,--test run unit tests\n" + " -h,--help this message\n" + "\n" + " <opts> includes all valid VODATA options\n" + "\n" + " Examples:\n\n" + " 1) Query for all X-ray image data of M51:\n\n" + " %% voimage -b x-ray any m51\n" + "\n" + " 2) Query an HST service having data of the subdwarf galaxy\n" + " IC 10, print a count of the results only:\n\n" + " %% voimage -c CADC/HST IC10\n" + "\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + + vo_taskTest (task, "--help", NULL); + + vo_taskTest (task, "-b", "x-ray", "any", "m51", NULL); // Ex 1 + vo_taskTest (task, "-c", "CADC/HST", "IC10", NULL); // Ex 2 + + vo_taskTestReport (self); +} diff --git a/vendor/voclient/voapps/voiminfo.c b/vendor/voclient/voapps/voiminfo.c new file mode 100644 index 00000000..fe2baa8d --- /dev/null +++ b/vendor/voclient/voapps/voiminfo.c @@ -0,0 +1,493 @@ +/* + * VOIMINFO -- Get the WCS information for a FITS image. + * + * Usage: + * voiminfo [<otps>] image.fits + * + * @file voiminfo.c + * @author Mike Fitzpatrick + * @date 11/03/12 + * + * @brief Get the WCS information for a FITS image. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <math.h> + +#include "votParse.h" /* keep these in order! */ +#include "voApps.h" +#include "fitsio.h" + + + +#define MAX_IMAGES 20480 /* max images to process */ +#define SZ_RESBUF 819200 + +#define OPT_ALL 0001 +#define OPT_BOX 0002 +#define OPT_CORNERS 0004 +#define OPT_EXTNS 0010 +#define OPT_FRAME 0020 +#define OPT_NAXES 0040 + + +static int do_return = 0; /* return result? */ + +/* Global task declarations. These should all be defined as 'static' to + * avoid namespace collisions. + */ +static int do_all = 0; /* print global values */ +static int do_sex = 0; /* print sexagesimal values */ + +static int do_box = 0; /* print box coordinates */ +static int do_corners = 0; /* print image corners */ +static int do_extns = 0; /* print extension values */ +static int do_info = 0; /* print image info */ +static int do_naxis = 0; /* print NAXIS values */ + +static int debug = 0; /* debug flag */ +static int verbose = 1; /* verbose flag */ + + +/* Task specific option declarations. Task options are declared using the + * getopt_long(3) syntax. + */ +int voiminfo (int argc, char **argv, size_t *len, void **result); + +static Task self = { "voiminfo", voiminfo, 0, 0, 0 }; +static char *opts = "%:habcdvnseio:r"; +static struct option long_opts[] = { + { "test", 1, 0, '%'}, /* --test is std */ + { "help", 2, 0, 'h'}, /* --help is std */ + { "return", 2, 0, 'r'}, /* --return is std */ + { "debug", 2, 0, 'd'}, /* debug flag */ + { "verbose", 2, 0, 'v'}, /* verbose flag */ + + { "all", 2, 0, 'a'}, /* print global value */ + { "box", 2, 0, 'b'}, /* print box values */ + { "corners", 2, 0, 'c'}, /* print image corner */ + { "extns", 2, 0, 'e'}, /* print each extn */ + { "info", 2, 0, 'i'}, /* print image info */ + { "naxes", 2, 0, 'n'}, /* print NEXIS values */ + { "output", 1, 0, 'o'}, /* output filename */ + { "sex", 2, 0, 's'}, /* sexagesimal values */ + { NULL, 0, 0, 0 } +}; + + +/** + * Private procedures. + */ +static void Usage (void); +static void Tests (char *input); +static char *fmt (double pos, int is_ra); +static char *fmt_naxis (char *imname, ImInfo *im, int do_all); +static char *fmt_box (char *imname, ImInfo *im, int do_all); +static char *fmt_corners (char *imname, ImInfo *im, int do_all); + +extern int vos_getURL (char *url, char *name); + + + +/** + * Application entry point. + */ +int +voiminfo (int argc, char **argv, size_t *reslen, void **result) +{ + /* These declarations are required for the VOApps param interface. + */ + char **pargv, optval[SZ_FNAME], resbuf[SZ_RESBUF]; + char imname[SZ_LINE]; + + + /* These declarations are specific to the task. + */ + char *oname = NULL, *imlist[MAX_IMAGES], *nimlist[MAX_IMAGES]; + int i, ch = 0, status = OK, pos = 0, nfiles = 0, narg = 0;; + size_t maxlen = SZ_RESBUF; + FILE *fd = (FILE *) NULL; + ImInfo *im; + + + /* Initialize result object whether we return an object or not. + */ + *reslen = 0; + *result = NULL; + memset (imlist, 0, MAX_IMAGES); + memset (nimlist, 0, MAX_IMAGES); + + + /* Parse the argument list. The use of vo_paramInit() is required to + * rewrite the argv[] strings in a way vo_paramNext() can be used to + * parse them. The programmatic interface allows "param=value" to + * be passed in, but the getopt_long() interface requires these to + * be written as "--param=value" so they are not confused with + * positional parameters (i.e. any param w/out a leading '-'). + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + while ((ch = vo_paramNext(opts,long_opts,argc,pargv,optval,&pos)) != 0) { + if (ch > 0) { + /* If the 'ch' value is > 0 we are parsing a single letter + * flag as defined in the 'opts string. + */ + switch (ch) { + case '%': Tests (optval); return (self.nfail); + case 'h': Usage (); return (OK); + case 'r': do_return=1; break; + case 'd': debug++; break; + case 'v': verbose++; break; + + case 'a': do_all++; break; + case 'b': do_box++; break; + case 'c': do_corners++; break; + case 'e': do_extns++; break; + case 'i': do_info++; break; + case 's': do_sex++; break; + case 'n': do_naxis++; break; + case 'o': oname = strdup (optval); break; + default: + fprintf (stderr, "Invalid option '%s'\n", optval); + return (1); + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + /* This code processes the positional arguments. The 'optval' + * string contains the value but since this string is + * overwritten w/ each arch we need to make a copy (and must + * remember to free it later. + */ + imlist[nfiles++] = strdup (optval); + narg++; + } + + if (narg > MAX_IMAGES) { + fprintf (stderr, "ERROR: Too many images to process\n"); + return (1); + } + } + + + /* Sanity checks. + */ + if (imlist[0] == NULL || strcmp (imlist[0], "-") == 0) { + free (imlist[0]); + imlist[0] = strdup ("stdin"); + nfiles = 1; + } + if (do_all && strcasecmp (imlist[0], "stdin") == 0) { + fprintf (stderr, "Error: Option not supported with standard input\n"); + return (ERR); + } + if (oname == NULL) oname = strdup ("stdout"); + if (strcmp (oname, "-") == 0) { free (oname), oname = strdup ("stdout"); } + + + /* Open the output file. + */ + if (strcmp (oname, "stdout") != 0) { + if ((fd = fopen (oname, "w+")) == (FILE *) NULL) { + fprintf (stderr, "Error: Cannot open output file '%s'\n", oname); + return (ERR); + } + } else + fd = stdout; + + /* Default to printing all info if we're not given a specific option. + if (!do_box && !do_corners && !do_info && !do_naxis) + do_info = 1; + */ + + + /** + * Main body of task + */ + for (i=0; i < nfiles; i++) { + + memset (imname, 0, SZ_LINE); + if (strncmp ("http://", imlist[i], 7) == 0) { + if (access ("/tmp/voiminfo.fits", F_OK) == 0) + unlink ("/tmp/voiminfo.fits"); + strcpy (imname, "/tmp/voiminfo.fits"); + if (vos_getURL (imlist[i], imname) <= 0) + continue; + } else + strcpy (imname, imlist[i]); + + if ((im = vot_imageInfo (imname, do_all)) ) { + memset (resbuf, 0, SZ_RESBUF); + if (do_info) { + vot_printImageInfo (fd, im); + } else if (do_naxis) { + strcpy (resbuf, fmt_naxis (imname, im, do_all)); + } else if (do_box) { + strcpy (resbuf, fmt_box (imname, im, do_all)); + } else if (do_corners) { + strcpy (resbuf, fmt_corners (imname, im, do_all)); + } else { + sprintf (resbuf, "%s\t%s\t%s\t%s\n", imlist[i], + fmt (im->frame.cx,1), fmt (im->frame.cy,0), + fmt (im->frame.radius,0)); + } + + if (do_return) + vo_appendResultFromString (resbuf, reslen, result, &maxlen); + else + fprintf (fd, "%s", resbuf); + + vot_freeImageInfo (im); + + if (strncmp ("http://", imlist[i], 7) == 0) + unlink (imname); + } + } + + + /* Clean up. Rememebr to free whatever pointers were created when + * parsing arguments. + */ + for (i=0; i < MAX_IMAGES; i++) { + if (imlist[i]) + free (imlist[i]); + if (nimlist[i]) + free (nimlist[i]); + else + break; + } + if (oname) free (oname); + if (fd != stdout) + fclose (fd); + + vo_paramFree (argc, pargv); + + return (status); /* status must be OK or ERR (i.e. 0 or 1) */ +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "voiminfo [<opts>] votable.xml\n\n" + " where\n" + " -%%,--test run unit tests\n" + " -h,--help this message\n" + "\n" + " -a,--all print all extns\n" + " -i,--info print image info\n" + " -b,--box print box values\n" + " -c,--corners print image corners\n" + " -n,--naxes print NAXIS values\n" + " -o,--output output filename\n" + " -s,--sex sexagesimal values\n" + "\n" + " -o,--output=<file> output file\n" + "\n" + "\n" + " Examples:\n\n" + " 1) Print the size of each image extension in an MEF file:\n\n" + " %% voiminfo -n mef.fits\n" + "\n" + " 2) Print the LL and UR positions of an image as sexigesimal:\n\n" + " %% voiminfo -b -s image.fits\n" + "\n" + " 3) Print the corner positions of an image as decimal degrees:\n\n" + " %% voiminfo -c image.fits\n" + "\n" + " 4) Print the box values for an entire mosaic MEF file:\n\n" + " %% voiminfo -b mef.fits\n" + "\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + char *mef = "data/mef.fits"; + char *sif = "data/sif.fits"; + char *opts[] = { "-a", "-i", "-b", "-c", "-n", "-s", NULL }; + register int i; + + + vo_taskTest (task, "--help", NULL); + + if (access (input, F_OK) == 0) { + vo_taskTest (task, "-n", input, NULL); // Ex 1 + vo_taskTest (task, "-b", "-s", input, NULL); // Ex 2 + vo_taskTest (task, "-c", input, NULL); // Ex 3 + vo_taskTest (task, "-b", input, NULL); // Ex 4 + } else + fprintf (stderr, "Warning: input file '%s' not found...\n", input); + + if (access (sif, F_OK) == 0) + for (i=0; opts[i]; i++) + vo_taskTest (task, opts[i], sif, NULL); + + if (access (mef, F_OK) == 0) + for (i=0; opts[i]; i++) + vo_taskTest (task, opts[i], mef, NULL); + + vo_taskTestReport (self); +} + + + +/***************************************************************************/ +/**** Private Procedures ****/ +/***************************************************************************/ + +/** + * FMT -- Output formatter. + */ +static char * +fmt (double pos, int is_ra) +{ + static char strbuf[10][SZ_LINE]; + static int bufnum = 0; + + + bufnum = (bufnum + 1) % 10; + memset (strbuf[bufnum], 0, SZ_LINE); + + pos = (pos < 0.0 ? -pos : pos); + + if (do_sex) { + int d, m; + float s, frac; + char sign = (pos < 0.0 ? '-' : ' '); + + pos = (is_ra ? (pos / 15.0) : pos); + d = (int) pos; + frac = (pos - d); + m = frac * 60.0; + s = ((frac * 60.0) - m) * 60.0; + + sprintf (strbuf[bufnum], "%c%02d:%02d:%04.1f", sign, d, m, s); + + } else + sprintf (strbuf[bufnum], "%f", pos); + + return (strbuf[bufnum]); +} + + +/** + * FMT_NAXIS -- Print the size of pixels of an image. + */ +static char * +fmt_naxis (char *imname, ImInfo *im, int do_all) +{ + static char line[SZ_RESBUF]; + + memset (line, 0, SZ_RESBUF); + if (im->nextend && !do_all) { + register int i = 0; + char buf[SZ_RESBUF]; + + for (i=0; i < im->nextend; i++) { + memset (buf, 0, SZ_RESBUF); + if (im->frame.naxis == 3) + sprintf (buf, "%s[%d]\t%d %d %d\n", imname, i, + im->extns[i].naxes[0], + im->extns[i].naxes[1], + im->extns[i].naxes[2]); + else + sprintf (buf, "%s[%d]\t%d %d\n", imname, i, + im->extns[i].naxes[0], im->extns[i].naxes[1]); + strcat (line, buf); + } + + } else { + if (im->frame.naxis == 3) + sprintf (line, "%s\t%d %d %d\n", imname, + im->frame.naxes[0], im->frame.naxes[1], im->frame.naxes[2]); + else + sprintf (line, "%s\t%d %d\n", imname, + im->frame.naxes[0], im->frame.naxes[1]); + } + + return (line); +} + + +/** + * FMT_BOX -- Print the corners of a box and rotation angle. + */ +static char * +fmt_box (char *imname, ImInfo *im, int do_all) +{ + static char line[SZ_RESBUF]; + + memset (line, 0, SZ_RESBUF); + if (im->nextend && !do_all) { + register int i = 0; + char buf[SZ_RESBUF]; + + for (i=0; i < im->nextend; i++) { + memset (buf, 0, SZ_RESBUF); + sprintf (buf, "%s[%d]\t%s %s\t%s %s\t%s\n", imname, i, + fmt (im->extns[i].lx,1), fmt (im->extns[i].ly,0), + fmt (im->extns[i].ux,1), fmt (im->extns[i].uy,0), + fmt (im->extns[i].rotang,0)); + strcat (line, buf); + } + + } else { + sprintf (line, "%s\t%s %s\t%s %s\t%s\n", imname, + fmt (im->frame.lx,1), fmt (im->frame.ly,0), + fmt (im->frame.ux,1), fmt (im->frame.uy,0), + fmt (im->frame.rotang,0)); + } + + return (line); +} + + +/** + * FMT_CORNERS -- Print the explicit corners of an image footprint. + */ +static char * +fmt_corners (char *imname, ImInfo *im, int do_all) +{ + static char line[SZ_RESBUF]; + + memset (line, 0, SZ_RESBUF); + if (im->nextend && !do_all) { + register int i = 0; + char buf[SZ_RESBUF]; + + for (i=0; i < im->nextend; i++) { + memset (buf, 0, SZ_RESBUF); + + sprintf (buf, "%s\t%s %s\t%s %s\t%s %s\t%s %s\n", imname, + fmt (im->extns[0].xc[0],1), fmt (im->extns[0].yc[0],0), + fmt (im->extns[0].xc[1],1), fmt (im->extns[0].yc[1],0), + fmt (im->extns[0].xc[2],1), fmt (im->extns[0].yc[2],0), + fmt (im->extns[0].xc[3],1), fmt (im->extns[0].yc[3],0)); + strcat (line, buf); + } + + } else { + sprintf (line, "%s\t%s %s\t%s %s\t%s %s\t%s %s\n", imname, + fmt (im->frame.xc[0],1), fmt (im->frame.yc[0],0), + fmt (im->frame.xc[1],1), fmt (im->frame.yc[1],0), + fmt (im->frame.xc[2],1), fmt (im->frame.yc[2],0), + fmt (im->frame.xc[3],1), fmt (im->frame.yc[3],0)); + } + return (line); +} diff --git a/vendor/voclient/voapps/voregistry.c b/vendor/voclient/voapps/voregistry.c new file mode 100644 index 00000000..a99c058f --- /dev/null +++ b/vendor/voclient/voapps/voregistry.c @@ -0,0 +1,1291 @@ +/** + * VOREGISTRY -- Registry resolution, query, and browsing + * + * + * Usage: voregistry [-<flags>] [ [<keyword>] | [<term>] ] + * + * -h,--help print this help + * -v,--verbose verbose mode + * --vverbose very-verbose mode + * + * -c,--count print a count of matching records + * -e,--exact print exactly matching records (resolve) + * -l,--list list full resource record + * -m,--meta list table metadata + * -r,--resolve resolution mode + + * -b,--bandpass <bandpass> constrain by bandpass + * -C,--clevel <level> constrain by content level + * -d,--dal constrain to only DAL services + * -g,--group group search terms + * -s,--subject <subject> constrain by subject string + * -t,--type <type> constrain by service type + * -N,--new <time> get only newly registered svcs + * -U,--updated <time> get only newly updated entries + * + * -a,--all print all results (default) + * -f,--fields <fields> output only specified fields + * -O,--or logically OR the search terms + * -n,--index <index> set index of result (-1 => list, 0 => all) + * -o,--output <oname> save results to <oname> as votable + * -B,--samp broadcast results as a SAMP message + * -V,--votable save results as VOTable + * -X,--xml save results as VOTable + * + * -I,--Id print only the Identifier (resolve mode) + * -L,--long print long lines of output (no wrapping) + * -R,--Resolve print the ShortName, ServiceType and ID + * -S,--SName print only the ShortName (resolve mode) + * -T,--Title print only the Title string (resolve mode) + * + * + * Resource Type Strings: + * catalog Cone search services + * image Simple Image Access services + * spectra Simple Spectral Access services + * table Vizier services + * <literal> ResourceType from Registry record + * + * Allowed Bandpass Strings: + * Radio Millimeter Infrared (IR) + * Optical Ultraviolet (UV) X-Ray (xray) + * Gamma-Ray (GR) + * + * Allowed Resource Fields (for -f flag): + * Title ShortName Identifier + * ServiceURL ReferenceURL Description + * Subject ResourceType Type + * Creator Publisher CoverageSpatial + * CoverageTemporal Waveband ContentLevel + * Version + * + * + * @file voregistry.c + * @author Mike Fitzpatrick, NOAO + * @date 8/03/07 + * + * @brief Registry resolution, query, and browsing + */ + +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <getopt.h> +#define _GNU_SOURCE +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include "VOClient.h" +#include "voApps.h" +#include "voAppsP.h" +#include "samp.h" + + +/* Local processing definitions. +*/ +#define M_RESOLVE 001 /* resolve to record field */ +#define M_SEARCH 002 /* search registry */ +#define M_FULL 004 /* print full record */ +#define M_METALIST 010 /* print table metadata */ + +#define MAX_TERMS 128 /* max search terms */ + +#define TIME_NEW 0 /* time-search types */ +#define TIME_UPDATE 1 + +#define TUNIT_HOURS 0 /* units of search */ +#define TUNIT_DAY 1 +#define TUNIT_MONTH 2 + + + +int mode = M_SEARCH; /* program mode */ + + +extern int count; /* return count of results */ +extern int verbose; /* verbose output? */ +extern int meta; /* print meta results */ +extern int proxy; /* use proxy server */ +extern int res_all; /* print all results */ +extern int longlines; /* don't format output */ +extern int group; /* group terms */ +extern int exact; /* exact match only? */ +extern int debug; /* debug output? */ +extern int nterms; /* number of search terms */ + +int exact = 0; /* exact match only? */ +int res_index = -1; /* index of result */ +int nresults = 0; /* no. of results */ +int user_fields = 0; /* uer-defined fields? */ +int orValues = 0; /* OR search terms? */ +int out_votable = 0; /* output a Resource VOTable */ +#ifdef REG10_KLUDGE +int reg10 = 0; /* Registry 1.0 support? */ +#endif +int dal_only = 0; /* DAL services only */ +int sortRes = 0; /* sort results? */ +int terse = 0; /* terse results? */ +int cset = 0; /* constraints set? */ +int do_samp = 0; /* broadcast SAMP result? */ +int timeSearch = 0; /* search by create/update time */ + + +char *fields = (char *) NULL; /* output fields */ +char *ofname = (char *) NULL; /* output filename */ +char *bandpass = (char *) NULL; /* bandpass constraint */ +char *subject = (char *) NULL; /* subject constraint */ +char *stype = (char *) NULL; /* service type constraint */ +char *clevel = (char *) NULL; /* content level constraint */ +char *terms[MAX_TERMS]; /* search words/terms */ + +char outname[SZ_FNAME]; /* output filename */ + + + +/* Task specific option declarations. + */ +int voregistry (int argc, char **argv, size_t *len, void **result); + +static Task self = { "voregistry", voregistry, 0, 0, 0 }; + +static void Usage (void); +static void Tests (char *input); + + +/* For getopt_long() option parsing. +*/ +int opt_index; +static char *opt_string = "aBb:C:cdef:ghn:IlLmOo:rRs:St:TvVX123789%"; + +static struct option long_options[] = { + + /* OUTPUT TYPES */ + { "count", 2, 0, 'c'}, /* count results */ + { "exact", 2, 0, 'e'}, /* exact results */ + { "list", 2, 0, 'l'}, /* list full record */ + { "meta", 2, 0, 'm'}, /* print metadata */ + { "resolve", 2, 0, 'r'}, /* resolve mode */ + + /* CONVENIENCE OPTS */ + { "id", 2, 0, 'I'}, /* ID Resolve mode */ + { "long", 2, 0, 'L'}, /* output long lines */ + { "Resolve", 2, 0, 'R'}, /* Resolve mode */ + { "SName", 2, 0, 'S'}, /* SName Resolve mode */ + { "Title", 2, 0, 'T'}, /* Title Resolve mode */ + + /* CONSTRAINT OPTS */ + { "bandpass", 1, 0, 'b'}, /* bandpass constraint */ + { "clevel", 1, 0, 'C'}, /* content level cons. */ + { "dal", 2, 0, 'd'}, /* DAL-only results */ + { "group", 2, 0, 'g'}, /* group terms */ + { "new", 1, 0, 'N'}, /* newly registered */ + { "updated", 1, 0, 'U'}, /* updated entried */ + { "subject", 1, 0, 's'}, /* subject constraint */ + { "type", 1, 0, 't'}, /* svctype constraint */ + + /* OUTPUT CONTROL OPTS */ + { "all", 2, 0, 'a'}, /* print all results */ + { "fields", 1, 0, 'f'}, /* set output fields */ + { "or", 2, 0, 'O'}, /* logically OR keyws */ + { "index", 1, 0, 'n'}, /* result index */ + { "output", 1, 0, 'o'}, /* output filename */ + { "samp", 2, 0, 'B'}, /* broadcase SAMP result */ + { "votable", 2, 0, 'V'}, /* output VOTable */ + { "xml", 2, 0, 'X'}, /* output XML */ + + /* STANDARD OPTS */ + { "help", 2, 0, 'h'}, /* print help */ + { "test", 2, 0, '%'}, /* unit tests */ + { "verbose", 2, 0, 'v'}, /* verbose flag */ + + /* ENGINEERING OPTS */ + { "debug", 2, 0, '1'}, /* debug output */ + { "dverb", 2, 0, '2'}, /* verbose debug output */ + { "reg10", 2, 0, '3'}, /* Registry 1.0 kludge */ + + { "tweet", 2, 0, '7'}, /* tweet output */ + { "sort", 2, 0, '8'}, /* */ + { "terse", 2, 0, '9'}, /* */ + + { NULL, 0, 0, 0 } +}; + + +/* The following is the full list of metadata available given the +** Registry query method we are using. This list will change when +** VOClient moves to a new Registry schema. + +char *resList[] = { // v0.4 output + "Title", "ShortName", "Identifier", + "ServiceURL", "ReferenceURL", "Description", + "Subject", "ResourceType", "Type", + "Creator", "Facility", "Instrument", + "Contributor", "CoverageSpatial", "CoverageTemporal", + "Waveband", "ContentLevel", "Version", + NULL +}; +*/ +char *resList[] = { /* resource fields (full print) */ + "Title", "ShortName", "Identifier", + "CapabilityStandardID", "Subject", "Type", + "ServiceURL", "ReferenceURL", "Description", + "Creator", "Publisher", "CoverageSpatial", + "CoverageTemporal", "Waveband", "ContentLevel", + "Version", "CapabilityName", + NULL +}; + +#define SZ_GBUF 256 +char gbuf[SZ_GBUF]; +/* +char *gfmt = "(ShortName like '%%%s%%' OR Identifier like '%%%s%%')"; +char *gfmt = "(Identifier like '%%%s%%')"; +*/ +char *gfmt = "(Identifier like '%s')"; + + +extern int errno; +extern int isSexagesimal (char *s), isDecimal (char *s); +extern int vot_regResolver (char *id, char *svctype, char *bpass, + char *subject, char *clevel, char *fields, int index, + int exact, int dal_only, char **result); +extern int vot_regSearch (char **ids, int nids, char *svctype, + char *bpass, char *subject, char *clevel, int orValues, + int votable, FILE *vot_fd, int dal_only, int sortRes, + int terse); +extern int vot_atoi (char *v); +extern char *strcasestr(); + + +static void printResolveRecord (void); +static void printResolveHdr (void); +static void printFullRecord (char *term); +static void printSvcMetadata (char *svc); + +static char *vot_getTime (int type, char *arg); +double vot_calJD (int mn, double dy, int yr, int hrs, int min, int sec); + +extern char *vot_toURL (char *arg); +extern void vot_printRegVOTableHdr (FILE *fd); +extern void vot_printRegVOTableRec (FILE *fd, RegResult resource, int recnum); +extern void vot_printRegVOTableTail (FILE *fd); + +extern void pretty_print (char *result, int nresults); +extern void pretty_print_table (char *result, int nresults, char *fields); +extern void ppMultiLine (char *result, int poffset, int pwidth, int maxchars); +extern void ppResSummary (char *result, int nresults); +extern void vot_printAttrs (char *fname, Query query, char *id); + + + + + +/************************************************************************ +** Program main() +*/ +int +voregistry (int argc, char *argv[], size_t *reslen, void **result) +{ + register int i=0, ch=0, arg_index=0, narg=0; + char vot_name[SZ_FNAME]; + int use_groups = 1; + int status = OK; + FILE *vot_fd = (FILE *) NULL; + + + *reslen = 0; + *result = NULL; + count = 0; + meta = 0; + vot_fd = stdout; + + memset (vot_name, 0, SZ_FNAME); + memset (outname, 0, SZ_FNAME); + + /* Process command line arguments. + */ + while (1) { + ch = getopt_long (argc, argv, opt_string, long_options, &opt_index); + + if (ch > 0) { + switch (ch) { + case 'h': + Usage (); + return (OK); + case '%': + Tests (NULL); + return (self.nfail); + + case 'a': /* print all results */ + res_all = 1; + break; + case 'c': /* count results */ + count++; + break; + case 'd': /* DAL-only results */ + dal_only++; + cset++; + break; + + + /* EXPERIMENTAL FLAGS */ + case '7': /* EXPERIMENTAL */ + terse += 2;; + break; + case '8': /* EXPERIMENTAL */ + sortRes++, terse++; + break; + case '9': /* EXPERIMENTAL */ + terse++; + break; + /* EXPERIMENTAL FLAGS */ + + + case 'e': /* exact results */ + exact++; + mode = M_RESOLVE; + break; + + case 'l': /* list full record */ + mode = M_FULL; + verbose = 2; + break; + case 'I': /* ID Resolve mode */ + mode = M_RESOLVE; + fields = "Identifier"; + user_fields++; + break; + case 'T': /* Title Resolve mode */ + mode = M_RESOLVE; + fields = "Title"; + user_fields++; + break; + case 'R': /* Resolve mode */ + mode = M_RESOLVE; + dal_only++; + fields = + "ShortName,CapabilityStandardID,Identifier,CapabilityName"; + user_fields++; + break; + case 'S': /* SName Resolve mode */ + mode = M_RESOLVE; + fields = "ShortName"; + user_fields++; + break; + case 'L': /* output long lines */ + longlines++; + break; + case 'g': /* group terms */ + mode = M_RESOLVE; + group++; + orValues++; + break; + case 'r': /* resolve mode */ + mode = M_RESOLVE; + break; + case 'm': + mode = M_METALIST; + dal_only++; + meta++; + break; + + case 'b': /* bandpass constraint */ + if (bandpass) { + fprintf (stderr,"Warning: Bandpass already specified."); + fprintf (stderr," Ignoring '%s'\n", optarg); + } else { + if (!optarg || (optarg && optarg[0] == '-')) { + fprintf (stderr, + "Error: the '-b' flag requires an argument\n"); + return (ERR); + } + bandpass = optarg; + } + cset++; + break; + case 's': /* subject constraint */ + if (subject) { + fprintf (stderr,"Warning: Subject already specified."); + fprintf (stderr," Ignoring '%s'\n", optarg); + } else { + if (!optarg || (optarg && optarg[0] == '-')) { + fprintf (stderr, + "Error: the '-s' flag requires an argument\n"); + return (ERR); + } + subject = optarg; + } + cset++; + break; + case 't': /* svctype constraint */ + if (stype) { + fprintf (stderr, "Warning: ServiceType already specified."); + fprintf (stderr, " Ignoring '%s'\n", optarg); + } else { + if (!optarg || (optarg && optarg[0] == '-')) { + fprintf (stderr, + "Error: the '-t' flag requires an argument\n"); + return (ERR); + } + stype = optarg; + } + cset++; + break; + case 'C': /* content level cons. */ + if (clevel) { + fprintf (stderr,"Warning: ContentLevel already specified."); + fprintf (stderr," Ignoring '%s'\n", optarg); + } else { + if (!optarg || (optarg && optarg[0] == '-')) { + fprintf (stderr, + "Error: the '-C' flag requires an argument\n"); + return (ERR); + } + clevel = optarg; + } + cset++; + break; + + case 'n': /* result index */ + res_index = vot_atoi (optarg); + break; + case 'o': /* logically OR keyws */ + out_votable++; + verbose = 2; + strcpy (outname, optarg); + break; + case 'O': /* logically OR keyws */ + orValues++; + break; + case 'f': /* set output fields */ + fields = optarg; + user_fields++; + break; + + case 'B': /* broadcase SAMP table */ + do_samp++; + out_votable++; + verbose = 2; + break; + case 'V': /* output VOTable */ + case 'X': /* output XML */ + out_votable++; + verbose = 2; + break; + + case 'v': /* verbose flag */ + verbose++; + break; + + case 'N': /* new resources */ + timeSearch++; + terms[nterms++] = vot_getTime (TIME_NEW, optarg); + break; + case 'U': /* updated entried */ + timeSearch++; + terms[nterms++] = vot_getTime (TIME_UPDATE, optarg); + break; + + /* "Engineering" flags. */ + case '1': /* debug */ + debug++; + break; + case '2': /* verbose debug */ + verbose++; + break; +#ifdef REG10_KLUDGE + case '3': /* Registry 1.0 kludge */ + reg10++; + break; +#endif + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + /* Parse the arguments. + ** + ** voregistry <keyw> [ <keyw> .... ] + ** + */ + char *arg, sql[SZ_SQL_TERM]; + int len, start, end; + + if ( (arg_index = optind + narg) >= argc) + break; + + arg = argv[arg_index]; + len = strlen (arg); + if (arg[0] == '\"') { + /* Capture all args forming a quoted string. + */ + bzero (sql, SZ_SQL_TERM); + do { + start = ((arg[0] == '\"') ? 1 : 0); + end = ((arg[len-1] == '\"') ? len-2 : len-1); + strncat (sql, &arg[start], end-start+1); + if (arg[len-1] == '\"') + break; + strcat (sql, " "); + arg = argv[++arg_index], narg++; + len = strlen (arg); + } while (arg); + terms[nterms++] = strdup (sql); + + } else if (access(arg, R_OK) == 0) { + FILE *fd; + char *name = calloc (1, SZ_FNAME); + + /* Process the file contents. + */ + if ((fd = fopen (arg, "r")) == (FILE *) NULL) { + fprintf (stderr, "ERROR: Cannot open file '%s'\n", arg); + exit (1); + } + while (fgets (name, SZ_FNAME, fd)) { + name[strlen(name)-1] = '\0'; /* kill newline */ + if (group) { + bzero (gbuf, SZ_GBUF); + sprintf (gbuf, gfmt, name, name); + terms[nterms++] = strdup (gbuf); + } else { + terms[nterms++] = strdup (name); + } + bzero (name, SZ_FNAME); + } + + fclose (fd); + free (name); + + } else { + if (strncasecmp("ivo://CDS/VizieR", arg, 16) == 0) { + char ivorn[SZ_LINE]; + + /* If we're using an 'old-style' Vizier ivorn, try + ** converting it to a a Registry 1.0 flavor. We'll + ** worry about further modifying the term if this fails + ** later on. + */ + bzero (ivorn, SZ_LINE); + strcpy (ivorn, strdup (arg)); + ivorn[9] = '.'; + terms[nterms++] = strdup (ivorn); + + } else + terms[nterms++] = strdup (arg); + } + + narg++; + + /* When we're done processing the arguments, break.... + */ + if (arg_index == (argc - 1)) + break; + } + } + + if (cset && nterms == 0) { + /* terms[nterms++] = "%"; */ + orValues = 0; + } + + + /* 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.voregistry") == ERR) + return (ERR); + + + /* See whether any flags negate other options, or imply values for + ** other fields. + */ + if (res_all) + res_index = -1; + if (nterms == 0 && !out_votable) { + if (mode == M_RESOLVE) + terms[nterms++] = strdup ("%"); + else { + mode = ((stype||clevel||subject||bandpass) ? M_SEARCH : M_RESOLVE); + + if (stype || clevel || subject || bandpass) + mode = M_SEARCH; + else { + if (! (stype || clevel || subject || bandpass)) + mode = M_SEARCH; + else + mode = M_RESOLVE; + } + if (stype && strcasestr (stype, "catalog")) + terms[nterms++] = strdup ("catalog"); + } + } +#ifdef FOO + if (fields && mode != M_RESOLVE) { + fprintf (stderr, "ERROR: 'fields' can only be used in Resolve Mode\n"); + voc_closeVOClient (0); /* close VOClient connection */ + return (ERR); + } +#endif + if (nterms == 0 && !stype && !bandpass && !clevel && !subject) { + char *name = calloc (1, SZ_FNAME); + + /* Process the arguments from the standard input. + */ + while (fgets (name, SZ_FNAME, stdin)) { + name[strlen(name)-1] = '\0'; /* kill newline */ + terms[nterms++] = strdup (name); + bzero (name, SZ_FNAME); + } + free (name); + } + if (mode == M_RESOLVE) + sortRes = 0; + + + /* If all of the terms appears to be Identfiers, try to optimize the + ** query, or reset the search mode. + */ + if (!stype && !clevel && !bandpass && !subject) { + + for (i=0; i < nterms; i++) { + if (strncmp("ivo:", terms[i], 4) || strncmp("htt:", terms[i], 4)) { + use_groups = 0; + break; + } + } + if (use_groups && mode == M_SEARCH) + mode = M_RESOLVE; + if (use_groups && nterms <= 20) { + group++; + orValues++; + for (i=0; i < nterms; i++) { + bzero (gbuf, SZ_GBUF); + sprintf (gbuf, gfmt, terms[i], terms[i]); + free (terms[i]); + terms[i] = strdup (gbuf); + } + } + } + + + /* If we're printing a VOTable, output the prolog. + */ + if (!meta && out_votable) { + strcpy (vot_name, (outname[0] ? outname : "/tmp/vot.xml")); + if (access (vot_name, F_OK) == 0) + unlink (vot_name); + if ((vot_fd = fopen (vot_name, "w+")) == (FILE *) NULL) { + fprintf (stderr, "Error opening SAMP result file.\n"); + return (ERR); + } + + vot_printRegVOTableHdr (vot_fd); + } + + switch (mode) { + case M_RESOLVE: + printResolveRecord (); + voc_closeVOClient (0); /* close VOClient connection */ + if (!meta && out_votable) + vot_printRegVOTableTail (vot_fd); + return ( (nresults == 0) ); + + case M_SEARCH: + if (!count) { + nresults = vot_regSearch (terms, nterms, stype, bandpass, + subject, clevel, orValues, out_votable, vot_fd, dal_only, + sortRes, terse); + } else { + if (orValues) { + for (i=0; i < nterms; i++) { + nresults = vot_regSearch (&terms[i], 1, stype, bandpass, + subject, clevel, 1, out_votable, vot_fd, dal_only, + sortRes, terse); + } + } else { + nresults = vot_regSearch (terms, nterms, stype, bandpass, + subject, clevel, 0, out_votable, vot_fd, dal_only, + sortRes, terse); + } + } + break; + + case M_FULL: + for (i=0; i < nterms; i++) + printFullRecord (terms[i]); + break; + + case M_METALIST: + if (nterms == 0) { + terms[nterms++] = "%"; + } + for (i=0; i < nterms; i++) + printSvcMetadata (terms[i]); + break; + + default: + fprintf (stderr, "Invalid mode.\n"); + exit (1); + } + + + /* Close the VOTable. + */ + if (!meta && out_votable) { + vot_printRegVOTableTail (vot_fd); + if (vot_fd != stdout) + fclose (vot_fd); + } + + /* If we're asked to print the output VOTable to the screen print it + * here. If an output name was specified it will have already been + * written, if the 'samp' flag was set assume that is the only desired + * output. + */ + if (!do_samp && out_votable && strcmp (vot_name, "/tmp/vot.xml") == 0) { + char line[SZ_LINE]; + + if ((vot_fd = fopen (vot_name, "r")) == (FILE *) NULL) { + fprintf (stderr, "Error opening VOTable result file.\n"); + return (ERR); + } + + memset (line, 0, SZ_LINE); + while (fgets (line, 4096, vot_fd)) { + fputs (line, stdout); + memset (line, 0, SZ_LINE); + } + + fclose (vot_fd); + } + + /* Broadcast the image as a message if requested. + */ + if (do_samp) { + int sampH = 0; + + if ((sampH = sampInit ("voatlas", "VOClient Task")) >= 0) { + char url[SZ_LINE]; + + memset (url, 0, SZ_LINE); + strcpy (url, vot_toURL (vot_name)); + + samp_setSyncMode (sampH); + sampStartup (sampH); /* initialize SAMP interface */ + + (void) samp_tableLoadVOTable (sampH, "all", url, NULL, NULL); + + sampShutdown (sampH); /* clean up */ + sampClose (sampH); + if (strcmp (vot_name, "/tmp/vot.xml") == 0) + unlink (vot_name); + } + } + + + return ( status ); +} + + +/************************************************************************ +** PRINTRESOLVERECORD -- Print a "complete" record for the resources +** matching the query string. +*/ +static void +printResolveRecord () +{ + char *result = (char *)NULL; + register int i; + + + /* Determine the fields we'll need. + */ + if (verbose == 1 && !fields) + fields = "ShortName,CapabilityStandardID,Title"; + if (verbose == 2 && !fields) + fields = "ShortName,CapabilityStandardID,Description"; + + if (out_votable) + fields = ""; + + if (out_votable) + fields = "Title,ShortName,Identifier,ServiceURL,ReferenceURL,CapabilityStandardID,ContentLevel,Type,Waveband,Creator,Subject,Version"; + + if (! out_votable) + printResolveHdr (); + + if (nterms == 0) { + terms[nterms++] = "%"; + exact = 1; + } + + for (i=0; i < nterms; i++) { +#ifdef REG10_KLUDGE + if (reg10 || strncasecmp("ivo://CDS.VizieR",terms[i],16) == 0) { + char ivorn[SZ_LINE]; + + bzero (ivorn, SZ_LINE); + strcpy (ivorn, terms[i]); + strcat (ivorn, "%"); + ivorn[9] = '/'; + + nresults = vot_regResolver (ivorn, stype, bandpass, subject, + clevel, fields, res_index, 0, dal_only, &result); + } else { +#endif + nresults = vot_regResolver (terms[i], stype, bandpass, subject, + clevel, fields, res_index, exact, dal_only, &result); +#ifdef REG10_KLUDGE + } +#endif + + if (! out_votable) { + if (count) { + if (nterms > 0 && terms[i][0] != '%') + printf ("%-20s %5d\t", terms[i], nresults); + else + printf ("%d", nresults); + if (verbose) + ppResSummary (result, nresults); + printf ("\n"); + } else if (user_fields) { + pretty_print_table (result, nresults, fields); + } else { + pretty_print (result, nresults); + } + } + + if (group) + break; + } + if (result) + free ((char *) result); +} + + +/************************************************************************ +** PRINTRESOLVEHDR -- Print the header information for Resolve mode. +*/ +static void +printResolveHdr () +{ + if (nterms == 0) + return; + if (count) { + if (verbose) { + printf ("\nShortName \t\tMatching Resources\n"); + printf ("-------------------------------------------"); + printf ("------------------------------------"); + } else { + printf ("\nShortName Matching Resources\n"); + printf ("-------------------------------------------"); + } + printf ("\n"); + + } else if (fields && !user_fields) { + printf("\nShortName ResourceType\t%s\n", + (verbose > 1 ? "Description" : "Title")); + printf("----------------------------------------"); + printf("----------------------------------------\n"); + } +} + + +/************************************************************************ +** PRINTFULLRECORD -- Print a "complete" recordfor the resources matching +** the query string. +*/ +static void +printFullRecord (char *term) +{ + RegResult resource = 0; + int i, j, nresults; + char *attr_val, sql[SZ_LINE]; + + + if (debug) + fprintf (stderr, "printFullRec: term='%s'\n", term); + + if (res_all) + sprintf (sql, "(ShortName like '%%%s%%') OR (Identifier like '%%%s%%')", + term, term); + else + sprintf (sql, "(ShortName like '%s') OR (Identifier like '%s')", + term, term); + + resource = voc_regExecute (voc_regQuery (sql, 0)); + nresults = voc_resGetCount (resource); + + if (nresults == 0 && !res_all) { + + if (strncasecmp("ivo://CDS.VizieR",term,16) == 0) { + char *ip, ivorn[SZ_LINE]; + + bzero (ivorn, SZ_LINE); + strcpy (ivorn, term); + for (ip = &ivorn[strlen(term)-1]; *ip != '/'; ip--) + *ip = '\0'; + *ip = '\0'; + + sprintf (sql, + "(ShortName like '%%%s%%') OR (Identifier like '%%%s%%')", + ivorn, ivorn); + } else + sprintf (sql, + "(ShortName like '%%%s%%') OR (Identifier like '%%%s%%')", + term, term); + + resource = voc_regExecute (voc_regQuery (sql, 0)); + nresults = voc_resGetCount (resource); + + if (nresults == 0) { + fprintf (stderr, "No results found for '%s'\n", term); + return; + } + } + + for (i=0; i < nresults; i++) { + if (out_votable) { + vot_printRegVOTableRec (stdout, resource, i); + + } else { + for (j=0; resList[j]; j++) { + if ((attr_val = voc_resGetStr (resource, resList[j], i))) { + if (strstr (resList[j], "StandardID")) + printf ("%16.16s: ", "ResourceType"); + else + printf ("%16.16s: ", resList[j]); + ppMultiLine((attr_val ? attr_val : "(none)"), 18, 61, 8192); + printf ("\n"); + } + } + if (nresults > 1 && i < (nresults - 1)) + printf ("------------------------------------------\n"); + } + } +} + + +/************************************************************************ +** PRINTSVCMETADATA -- Print the column metadata for the named service. +*/ +static void +printSvcMetadata (char *svc) +{ + RegResult resource = 0; + RegQuery rquery = 0; + int i, nresults; + char *type, *url, sql[SZ_LINE]; + DAL dal; + Query query; + + + if (res_all) + sprintf (sql, "(ShortName like '%%%s%%') OR (Identifier like '%%%s%%')", + svc, svc); + else + sprintf (sql, "(ShortName like '%s') OR (Identifier like '%s')", + svc, svc); + + if (debug) fprintf (stderr, "metalist sql = '%s'\n", sql); + + rquery = voc_regQuery (sql, 0); + + if (bandpass && bandpass[0]) + voc_regConstWaveband (rquery, bandpass); + if (stype && stype[0]) + voc_regConstSvcType (rquery, stype); + if (dal_only) + voc_regDALOnly (rquery, dal_only); + voc_regSortRes (rquery, sortRes); + + resource = voc_regExecute (rquery); + nresults = voc_resGetCount (resource); + + if (debug) fprintf (stderr, "query nres = %d\n", nresults); + + for (i=0; i < nresults; i++) { + if ((type = voc_resGetStr (resource, "CapabilityStandardID", i))) { + int len; + + url = voc_resGetStr (resource, "ServiceURL", i); + + /* Clean up any dangling '&' in the URL. + */ + len = strlen (url); + if (strcmp(&url[len-5], "&") == 0) + url[len-5] = '\0'; + + /* Form a dummy query for the metadata. + */ + if (strcasecmp ("CONE", type) == 0 || + strncasecmp ("TABULAR", type, 7) == 0) { + dal = voc_openConeConnection (url); + + /* As of 1/28/09 the Vizier SCS doesn't respond properly + ** to SR=0 for a metadata query, however if we leave off + ** the query params entirely we do get a valid response. + ** This is just a kludge. + ** + query = voc_getConeQuery (dal, 0.0, 0.0, + (strstr (url, "vizier")) ? -1.0 : 0.0); + ** FIXME */ + /* FIXME */ + + /* This is the standard SCS way to get metadata. For now + ** we'll do as the spec says and broken services will + ** have to be fixed. + */ + query = voc_getConeQuery (dal, 0.0, 0.0, 0.001); + + (void) voc_addIntParam (query, "VERB", + (meta ? 3 : min(3,verbose+1)) ); + + if (debug) { + fprintf (stderr, "Executing Metadata Query:\n %s\n\n", + voc_getQueryString (query, CONE_CONN, 0)); + } + + /* + printf ( + "\n# ---- Svc: %s (%s) ---------------------------\n\n", + svc, type); + */ + vot_printAttrs (NULL, query, svc); + + } else if (strncasecmp ("SIAP", type, 4) == 0) { + dal = voc_openSiapConnection (url); + query = voc_getSiapQuery (dal, 0.0, 0.0, 0.0, 0.0, "METADATA"); + (void) voc_addIntParam (query, "VERB", verbose); + + /* + printf ("\n# ---- Svc: %s (%s) ---------------------------\n\n", + svc, type); + */ + vot_printAttrs (NULL, query, svc); + } + } + } +} + + +/************************************************************************ +** GETLONGLINES -- Utility procedure to return the value of the 'longlines' +** flag. +*/ +int +vot_getLonglines () +{ + return (longlines); +} + + +/************************************************************************ +** GETTME -- Cteate a time-constrainst string for the search. +*/ +#define SZ_TSTR 32 +#define SZ_TQUERY 256 + +static char * +vot_getTime (int type, char *arg) +{ + char unit = arg[strlen (arg) - 1]; + long diff, val; + time_t now = time((time_t)NULL), then; + struct tm *start, *end; + static char t1[SZ_TSTR], t2[SZ_TSTR], tquery[SZ_TQUERY]; + + + val = atoi (arg); + if (!isdigit(unit)) { /* get units of search */ + if (strchr ("hH", (int) unit)) + diff = val * 3600; + else if (strchr ("dD", (int) unit)) + diff = val * (3600 * 24); + else if (strchr ("wW", (int) unit)) + diff = val * (3600 * 24 * 7); + else if (strchr ("mM", (int) unit)) + diff = val * (3600 * 24 * 30); + } else + diff = val * (3600 * 24); + + then = now - diff; + + memset (t1, 0, SZ_TSTR); + start = localtime (&then); + sprintf (t1, "%4d-%02d-%02dT%02d:%02d:%02d", + (start->tm_year+1900), start->tm_mon+1, start->tm_mday, + start->tm_hour, start->tm_min, start->tm_sec); + + memset (t2, 0, SZ_TSTR); + end = localtime (&now); + sprintf (t2, "%4d-%02d-%02dT%02d:%02d:%02d", + (end->tm_year+1900), end->tm_mon+1, end->tm_mday, + end->tm_hour, end->tm_min, end->tm_sec); + + sprintf (tquery, + "[@%s] >= '%s' AND [@%s] <= '%s'", + (type == TIME_NEW ? "created" : "updated"), t1, + (type == TIME_NEW ? "created" : "updated"), t2); + /* + sprintf (tquery, "[@%s] >= '%s'", + (type == TIME_NEW ? "created" : "updated"), t1); + */ + return ( strdup(tquery) ); +} + + +/* Get JD from date. Not entirely accurate, but good enough for what we need. +*/ +double +vot_calJD (int mn, double dy, int yr, int hrs, int min, int sec) +{ + int a, b, d, m, y; + long c; + double mjp; + + + m = mn; + y = (yr < 0) ? yr + 1 : yr; + if (mn < 3) + m += 12, y -= 1; + + if (yr < 1582 || (yr == 1582 && (mn < 10 || (mn == 10 && dy < 15)))) + b = 0; + else + a = y/100, b = 2 - a + a/4; + + c = ((y < 0) ? + (long)((365.25*y) - 0.75) - 694025L : (long)(365.25*y) - 694025L); + d = (int)(30.6001*(m+1)); + + mjp = b + c + d + dy - 0.5; + + mjp += (((double)hrs / 24.) + ((double)min / 60.) + ((double)sec / 3600.)); + return (mjp); +} + + + + +/************************************************************************ +** USAGE -- Print a help summary for the task. +*/ +static void +Usage () +{ + printf ("\n\ + Usage: voregistry [-<flags>] [ [<keyword>] | [<term>] ]\n\ + \n\ + -h,--help print this help\n\ + -v,--verbose verbose mode\n\ + --vverbose very-verbose mode\n\ + \n\ + -c,--count print a count of matching records\n\ + -e,--exact print exactly matching records (resolve)\n\ + -l,--list list full resource record\n\ + -m,--meta list table metadata\n\ + -r,--resolve resolution mode\n\ + \n\ + -b,--bandpass <bandpass> constrain by bandpass\n\ + -C,--clevel <level> constrain by content level\n\ + -d,--dal constrain to only DAL services\n\ + -g,--group group search terms\n\ + -s,--subject <subject> constrain by subject string\n\ + -t,--type <type> constrain by service type\n\ + -N,--new <time> get only newly registered svcs\n\ + -U,--updated <time> get only newly updated entries\n\ + \n\ + -a,--all print all results (default)\n\ + -f,--fields <fields> output only specified fields\n\ + -O,--or logically OR the search terms\n\ + -n,--index <index> set index of result (-1 => list, 0 => all)\n\ + -o,--output <oname> save results to <oname> as votable\n\ + -B,--samp broadcast results as a SAMP message\n\ + -V,--votable save results as VOTable\n\ + -X,--xml save results as VOTable\n\ + \n\ + -I,--Id print only the Identifier (resolve mode)\n\ + -L,--long print long lines of output (no wrapping)\n\ + -R,--Resolve print the ShortName, ServiceType and ID\n\ + -S,--SName print only the ShortName (resolve mode)\n\ + -T,--Title print only the Title string (resolve mode)\n\ + \n\ + \n\ + Resource Type Strings:\n\ + catalog Cone search services\n\ + image Simple Image Access services\n\ + spectra Simple Spectral Access services\n\ + table Vizier services\n\ + <literal> ResourceType from Registry record\n\ + \n\ + Allowed Bandpass Strings:\n\ + Radio Millimeter Infrared (IR)\n\ + Optical Ultraviolet (UV) X-Ray (xray)\n\ + Gamma-Ray (GR)\n\ + \n\ + Allowed Resource Fields (for -f flag):\n\ + Title ShortName Identifier\n\ + ServiceURL ReferenceURL Description\n\ + Subject ResourceType Type\n\ + Creator Publisher CoverageSpatial\n\ + CoverageTemporal Waveband ContentLevel\n\ + Version\n\ + \n\ + \n\ + \n\ + Examples:\n ---------\n\n\ + \n\ + 1) Get a count of all the SIAP services available in the,\n\ + Registry, then list more information about each:\n\ + \n\ + %% voregistry --count --type=image\n\ + 171\n\ + %% voregistry -rv -t image\n\ + \n\ + 2) Find all catalog (i.e. Cone) services using the search\n\ + words 'radio' and 'galaxies':\n\ + \n\ + %% voregistry -t catalog radio galaxies\n\ + \n\ + 3) Print the full resource record of the GSC2.3 catalog at STScI:\n\ + \n\ + %% voregistry --list GSC2.3\n\ + "); + + printf ("\n\n"); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + vo_taskTest (task, "--help", NULL); + + vo_taskTest (task, "--count", "--type=image", NULL); // Ex 1 + vo_taskTest (task, "-rv", "-t", "image", NULL); // Ex 1 + vo_taskTest (task, "-t", "catalog", "radio", "galaxies", NULL); // Ex 2 + vo_taskTest (task, "--list", "GSC2.3", NULL); // Ex 3 + + vo_taskTest (task, "-b", "radio", "abell", NULL); + vo_taskTest (task, "-rvv", "-n", "1", "J/A+A/446/97", NULL); + vo_taskTest (task, "-v", "-t", "image", "wfpc", NULL); + vo_taskTest (task, "-cv", "keck", NULL); + vo_taskTest (task, "-c", "chandra", "hst", "spitzer", NULL); + vo_taskTest (task, "-co", "chandra", "hst", "spitzer", NULL); + vo_taskTest (task, "Facility like 'HST'", NULL); + vo_taskTest (task, "Title like '%Keck%'", NULL); + vo_taskTest (task, "--new", "3m", NULL); + vo_taskTest (task, "--new", "3m", "cool", "stars", NULL); + vo_taskTest (task, "--updated", "12m", "--count", NULL); + + vo_taskTestReport (self); +} diff --git a/vendor/voclient/voapps/vosamp.c b/vendor/voclient/voapps/vosamp.c new file mode 100644 index 00000000..4cc49d08 --- /dev/null +++ b/vendor/voclient/voapps/vosamp.c @@ -0,0 +1,2298 @@ +/** + * VOSAMP - Example task to send a single SAMP message for the cmdline. + * + * Usage: + * + * vosamp [<opts>] <cmd> [args ...] + * + * Where + * <cmd> command to process + * -%,--test run unit tests + * -h,--help print help summary + * -d,--debug debug output + * -v,--verbose verbose output + * -q,--quiet suppress all output + * + * -i,--interactive interactive mode + * -m,--many handle multiple messages + * -s,--sender <sender> handle only messages from <sender> + * + * -t,--to <to> send to specified application (or all) + * -p,--pattern <pattern> message pattern: sync|async|notify + * -f,--file <file> send all commands in the file + * -n,--nokeepalive disable keep_alive feature + * + * -P,--proxy <pattern> proxy process connection + * -T,--timeout <N> keepalive timeout + * -S,--session <name> session name + * + * -r,--return return result to API + * + * + * Subcommands: + * + * snoop print all received messages + * + * session list list all nodes in current session + * session leave|exit|logout leave the current session + * session <name> join the named session + * + * status print Hub availability + * list list all registered clients + * access <appName> print <appName> availability + * handle <mtype> wait for <mtype> message + * + * send <mtype> [<args> ...] generalized <mtype> message send + * exec <cmd> execute a client command + * pointAt <ra> <dec> point at given coords + * setenv <name> <value> set an environment value + * getenv <name> get an environment value + * setparam <name> <value> set a parameter value + * getparam <name> get a parameter value + * + * load <url> load the named image/table file + * loadImage <url> load the named image + * loadVOTable <url> load the named VOTable + * loadFITS <url> load the named FITS bintable + * showRow [<tblId>] [<url>] <row> highlight specified row + * selectRows [<tblId>] [<url>] <rows> select specified rows + * bibcode <bibcode> load the named bibcode + * + * + * @file vosamp.c + * @author Mike Fitzpatrick + * @date 6/03/12 + * + * @brief Desktop SAMP messaging utility. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <fcntl.h> +#include <time.h> + +#include <netdb.h> +#include <sys/errno.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + + +#include "samp.h" /* LIBSAMP interface */ +#include "voApps.h" /* voApps interface */ + + +#define SZ_MTYPE 64 +#define SZ_BUF 128 +#define SZ_HOSTIP 16 +#define SZ_APPNAME 16 +#define SZ_BLOCK 4096 + +#define HUB_TIMEOUT /* allow timeout */ + +#define ENV_PROXY "VOSAMP_PROXY" + + +#define MAX_ARGS 8 +#define VOS_TIMEOUT 600 /* 10-min proxy timeout */ +#define VOS_DEFPORT 3999 +#define VOS_HUBWAIT 3 + +#define MATCH(s) (strcasecmp(cmd,s)==0) + + +char senderIP[SZ_HOSTIP]; +char fname[SZ_FNAME]; +char *to = NULL; + +static int sampH = 0; /* samp struct handle */ + + /* task options */ +static int verbose = 0; /* verbose output */ +static int quiet = 0; /* suppress all output */ +static int debug = 0; /* verbose output */ +static int interact = 0; /* interactive shell */ +static int multiple = 0; /* accept multiple msgs */ +static int xml_trace = 0; /* trace XML_RPC */ +static int keep_alive = 1; /* lingering connection */ +static int proxy_pid = 0; /* proxy vosamp pid */ +static int proxy_port = VOS_DEFPORT; /* proxy vosamp port */ + +static int svr_sock = 0; /* child server socket */ +static int ipc_sock = 0; /* IPC sock (parent/child) */ +static int session_sock = 0; /* session mgr socket */ +static int input_sock = 0; /* cmd input socket */ +static int use_ipc = 1; /* use IPC */ +static int have_dotfile = 0; /* have a valid .vosamp? */ +static int in_parent = 1; /* are we parent process? */ +static int do_return = 1; /* return result to API */ +static int return_stat = OK; /* return status */ +static int numargs = 0; /* number of cmdline args */ +static int timeout = VOS_TIMEOUT; /* child timeout */ + +static int hub_connected = 0; /* connected to SAMP hub */ +static int sess_connected = 0; /* connected to session mgr */ + +char *session_host = SESS_DEFHOST; /* session manager host IP */ +int session_port = SESS_DEFPORT; /* session manager port */ + +static char *proxy = NULL; /* proxy connection string */ +static char *session = NULL; /* session name */ +static char *pattern = NULL; /* SAMP msg pattern */ +static char *cmdfile = NULL; /* input command file */ +static char *filt_mtype = NULL; /* snoop filter mtype */ +static char *filt_sender = NULL; /* snoop sender name */ +static char cmd[SZ_CMD]; /* command name */ +static char cmdline[SZ_CMD]; /* full command line */ +static char proxy_host[SZ_FNAME]; /* proxy vosamp host name */ +static char dotfile[SZ_FNAME]; /* path to local dotfile */ +static char psession[SZ_FNAME]; /* proxy file session name */ +static char *args[MAX_ARGS]; /* command args buffer */ + +static FILE *fd = (FILE *) NULL; +static fd_set allset, fds; +static struct timeval tm; + + +static int vos_sendToProxy (char *cmdline); +static int vos_startProxy (void); +static int vos_sampInit (void); +static int vos_sendCmd (int sock, char *cmdline); +static int vos_invalidArg (int argc, char *argv[], int nargs, int exist); +static void vos_sampShutdown (void); +static void vos_cmdHelp (char *cmd); +static void vos_procCmd(int sampH, char *to, char *cmd, char **argv, int argc); +static void vos_handleCmdInput (void); +static void vos_msgHandler (char *sender, char *mtype, char *msg_id, Map map); +static void vos_sessionHandler (char *sender, char *mtype, char *id, Map map); +static void vos_forwardCmd (char *sess_cmd); +static void vos_printMessage (char *mtype, char *sender, Map map); + +static void vos_rewriteCmd (char *line, char *fname); +static void vosDebug (char *format, ...); +static char *vos_rewriteURL (char *in); +static char *vos_dotFile (); + +int vos_uploadFiles (int fd, char *cmdline); +int vos_recvFile (int sock, int size, char *fname); +int vos_sendFile (int sock, char *path, char *fname); +int vos_openSession (char *host, int port, char *session_name); +int vos_closeSession (int sock); + + +extern char *vos_toURL (char *arg); +extern char *vos_optArg (char *arg); +extern char *vos_getLocalIP (void); +extern char *vos_getFName (char *url); +extern char *vos_typeName (int type); +extern int *vos_toIntArray (char *arg, int *nrows); +extern int vot_atoi (char *v); + + +/* Utility socket routines. + */ +extern int vos_fileRead (int fd, void *vptr, int nbytes); +extern int vos_fileWrite (int fd, void *vptr, int nbytes); +extern int vos_openServerSocket (int port); +extern int vos_openClientSocket (char *host, int port, int retry); +extern int vos_testClientSocket (char *host, int port); +extern int vos_sockRead (int fd, void *vptr, int nbytes); +extern int vos_sockWrite (int fd, void *vptr, int nbytes); +extern int vos_sockWriteHdr (int fd, int len, char *name, int type, + int mode, char *to); +extern int vos_sockReadHdr (int fd, int *len, char *name, int *type, + int *mode); +extern int vos_urlType (char *url); +extern int vos_getURL (char *url, char *fname); + +extern double vot_atof (char *v); + +extern void vos_setNonBlock (int sock); +extern struct hostent *vos_getHostByName (char *lhost); +extern struct hostent *vos_dupHostent (struct hostent *hentry); + + + +/* Task specific option declarations. + */ +int vosamp (int argc, char **argv, size_t *len, void **result); + +static Task self = { "vosamp", vosamp, 0, 0, 0 }; +static char *opts = "%:hnrdif:mps:t:vP:T:S:"; +static struct option long_opts[] = { + { "return", 0, 0, 'r'}, /* task option */ + { "help", 2, 0, 'h'}, /* required */ + { "test", 1, 0, '%'}, /* required */ + { "debug", 2, 0, 'd'}, /* debug */ + { "verbose", 2, 0, 'v'}, /* verbose output */ + { "quiet", 2, 0, 'q'}, /* suppress output */ + { "many", 2, 0, 'm'}, /* multiple msgs */ + { "sender", 1, 0, 's'}, /* sender filter */ + { "interactive", 2, 0, 'i'}, /* interactive mode */ + { "file", 1, 0, 'f'}, /* cmd file */ + { "pattern", 1, 0, 'p'}, /* msg pattern */ + { "proxy", 1, 0, 'P'}, /* proxy connection */ + { "session", 1, 0, 'S'}, /* session name */ + { "to", 1, 0, 't'}, /* recipient name */ + { "nokeepalive", 2, 0, 'n'}, /* keep connection */ + { "timeout", 1, 0, 'T'}, /* connection timeout */ + { NULL, 0, 0, 0 } +}; + +static void Usage (void); +static void Tests (char *input); + + + +/**************************************************************************** + * Program entry point. + */ +int +vosamp (int argc, char **argv, size_t *reslen, void **result) +{ + char **pargv, optval[SZ_FNAME], ch, *env_proxy = NULL; + int i, pos = 0, len = 0; + time_t expiry; + + + /* Initialize. + */ + memset (cmd, 0, SZ_CMD); + memset (cmdline, 0, SZ_CMD); + memset (dotfile, 0, SZ_FNAME); + memset (psession, 0, SZ_FNAME); + memset (proxy_host, 0, SZ_FNAME); + + strcpy (proxy_host, vos_getLocalIP ()); + strcpy (dotfile, vos_dotFile ()); + for (i=0; i < MAX_ARGS; i++) + args[i] = calloc (1, SZ_LINE); + + *reslen = 0; + *result = NULL; + return_stat = OK; + + + /* Parse the argument list. + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + i = 0; + while ((ch = vo_paramNext (opts,long_opts,argc,pargv,optval,&pos)) != 0) { + i++; + if (ch > 0) { + switch (ch) { + case '%': Tests (optval); return (self.nfail); + case 'h': Usage (); return (OK); + + case 'd': debug++; break; + case 'v': verbose++; break; + case 'q': quiet++; break; + case 'n': keep_alive = 0; break; + case 'm': multiple++; break; + case 'i': interact++; break; + + case 's': filt_sender = strdup (optval); i++; break; + case 'f': cmdfile = strdup (optval); i++; break; + case 't': to = strdup (optval); i++; break; + case 'p': pattern = strdup (optval); i++; break; + case 'P': proxy = strdup (optval); i++; break; + case 'S': session = strdup (optval); i++; break; + case 'T': timeout = vot_atoi (optval); i++; break; + + case 'r': do_return=1; break; + default: + fprintf (stderr, "Invalid option '%s'\n", optval); + return (1); + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + /* Remainder of argv is the subcommand and its arguments. + */ + if (pargv[i] == NULL) + break; + if (!cmd[0]) { + strcpy (cmd, optval); + } else { + if (strcasecmp (cmd, "exec") == 0 || + strcasecmp (cmd, "echo") == 0) { + strcat (args[0], optval); + strcat (args[0], " "); + } else { + char *ip; + + while (pargv[i]) { + if (strstr (pargv[i], "://") == NULL) { + /* replace ':' w/ '=' */ + for (ip=pargv[i]; *ip; ip++) + *ip = ((*ip == ':') ? '=' : *ip); + } + strcpy (args[numargs++], pargv[i++]); + } + break; + } + } + } + } + + + /* Print command help if that's all we're asked. + */ + if (strncmp (cmd, "?", 1) == 0 || strncasecmp (cmd, "help", 4) == 0) { + Usage (); + return (OK); + } + if (strncmp(args[0], "?", 1) == 0 || strncasecmp(args[0], "help", 4) == 0) { + vos_cmdHelp (cmd); + return (OK); + } + if (strncmp(cmd, "access", 6) == 0 && strncasecmp(args[0], "hub", 3) == 0) { + int hub_connected = vos_sampInit (); + + printf ("%s\n", (hub_connected ? "yes" : "no")); + if (hub_connected) + vos_sampShutdown (); + return ( (hub_connected ? OK : ERR) ); + } + if (strcmp (cmd, "handle") == 0 || strcmp (cmd, "snoop") == 0) + keep_alive = 0; + + + /* Sanity checks. + */ + if (interact || argc <= 1) + cmdfile = strdup ("-"); + if (to == NULL) + to = strdup ("all"); + if (pattern == NULL) + pattern = strdup ("async"); + + + /* Initialize the SAMP interface. + tm.tv_sec = VOS_HUBWAIT; + */ + tm.tv_sec = timeout; + tm.tv_usec = 0; + session_sock = 0; + + + /* Check for environment definitions. + */ + if ((env_proxy = getenv (ENV_PROXY))) + proxy = strdup (env_proxy); + + if (proxy) { + /* We've been asked to send the command to a particular proxy, just + * send the command line and any required data. + */ + char *cp = strchr (proxy, (int)':'); + + vosDebug ("Using proxy '%s'\n", proxy); + if (cp) { + proxy_port = vot_atoi (cp+1); + *cp = '\0'; + strcpy (proxy_host, proxy); + } else { + proxy_port = VOS_DEFPORT; + strcpy (proxy_host, proxy); + } + use_ipc++; + have_dotfile++; + ipc_sock = vos_openClientSocket (proxy_host, proxy_port, 1); + + } else { + /* See if we have a local proxy running we can use instead of starting + * a new connection. Data references remain local unless being + * passed on to the session manager service. + */ + FILE *fd = (FILE *) NULL; + + if (keep_alive && access (dotfile , R_OK) == 0) { + if ((fd = fopen (dotfile, "r+")) != (FILE *) NULL) { + time_t now = time ((time_t) 0); + int test = 0; + + /* Read the dotfile contents. + */ + fscanf (fd, "%s %d %d %ld %s", + proxy_host, &proxy_port, &proxy_pid, &expiry, psession); + fclose (fd); + + + /* Make sure we can reach the running proxy, otherwise + * assume it is a stale dotfile. + */ + if ((test = vos_testClientSocket(proxy_host, proxy_port)) < 0) { + if (verbose) + fprintf (stderr, "Removing stale .vosamp file ...\n"); + unlink (dotfile); + goto samp_init; + } else { + vos_sockWriteHdr (test, 0, NULL, SAMP_TEST, 0, "proxy"); + close (test); + } + + /* Check for a stale dotfile. */ + if (now <= (expiry - 2)) { + use_ipc++; + have_dotfile++; + } else { + if (verbose) + fprintf (stderr, "Removing stale .vosamp file ...\n"); + unlink (dotfile); + goto samp_init; + } + } + } else { + /* First do some sanity checks on the command. If we're asked + * to quit, then simply don't connect. + */ + if (strncasecmp ("quit", cmd, 4) == 0) { + return (OK); + } + + /* No remote command specified, no local connection, so connect to + * the Hub as a new application. + * + * Start the keep-alive proxy server. + */ +samp_init: + if (keep_alive) { + vos_startProxy (); + use_ipc = 1; + } else { + if (! (hub_connected = vos_sampInit ())) { + fprintf (stderr, "Error: cannot connect to Hub.\n"); + return (ERR); + } + use_ipc = 0; + } + } + } + + + /* Process a single command if we're not in keep_alive mode. + */ + if (!keep_alive) { + vos_procCmd (sampH, to, cmd, args, numargs); + goto cleanup_; + } + + /* Open an IPC socket to the proxy. + */ + while (in_parent && ipc_sock <= 0) { + vosDebug ("opening ipc socket to %s:%d\n", proxy_host, proxy_port); + ipc_sock = vos_openClientSocket (proxy_host, proxy_port, 1); + if (ipc_sock < 0) { + if (verbose) + fprintf (stderr, "Cannot open client ipc_sock\n"); + sleep (1); + } + } + vosDebug ("ipc socket %d\n", ipc_sock); + + + /* Process the messages in the named file, or from the cmdline. Since + * there is some overhead in connecting to the hub, this is an efficient + * way to send multiple messages from a single connection. + */ + + if (cmdfile) { + fd = (cmdfile[0] == '-' ? stdin : fopen (cmdfile, "r")); + + /* Send the command string from the stdin or the cmd file. + */ + fprintf (stderr, "vosamp> "); +#ifdef FGETS + while (fgets (cmdline, SZ_CMD, fd) && !feof (fd) && !ferror (fd)) { +#else + FD_ZERO (&allset); + FD_SET (fileno (stdin), &allset); + while (1) { + memcpy (&fds, &allset, sizeof(allset)); + if (select (8, &fds, NULL, NULL, NULL) == 0) + continue; + + if (fgets (cmdline, SZ_CMD, stdin) == NULL) + continue; +#endif + len = strlen (cmdline); + if (cmdline[len-1] == '\n') + cmdline[len-1] = '\0'; + + if (strncasecmp (cmdline, "quit", 4) == 0 || + strncasecmp (cmdline, "logo", 4) == 0) + break; + else if (cmdline[0]) { + vos_sendToProxy (cmdline); + fprintf (stderr, "vosamp> "); + } + } + + if (fd != stdin) + fclose (fd); + + } else if (cmd[0]) { + /* Send the command string from the commandline. + */ + int i, len = 0; + + memset (cmdline, 0, SZ_CMD); + sprintf (cmdline, "%s %s ", cmd, args[0]); + for (i=1; i < numargs; i++) { + strcat (cmdline, args[i]); + strcat (cmdline, " "); + } + len = strlen (cmdline); cmdline[len-1] = '\0'; + + vos_sendToProxy (cmdline); + } + close (ipc_sock); + + + /* Close down and clean up. + */ +cleanup_: + if (!keep_alive) + vos_sampShutdown (); + + if (to) free ((void *) to); + if (proxy) free ((void *) proxy); + if (cmdfile) free ((void *) cmdfile); + if (pattern) free ((void *) pattern); + if (session) free ((void *) session); + if (filt_sender) free ((void *) filt_sender); + + return (return_stat); +} + + +/** + * VOS_SENDTOPROXY -- Send a cmdline to the proxy. + */ +static int +vos_sendToProxy (char *cmdline) +{ + /* See if we need to join a session before processing the cmd. + */ + if (session && psession[0] != '\0') { + /* Have session param and running a proxy. + */ + memset (cmdline, 0, SZ_CMD); + sprintf (cmdline, "session %s", session); + + } else if (strcasecmp (cmd, "session") == 0 && + (psession[0] && strcasecmp (psession, "none") == 0)) { + /* Have session command and not running a proxy. + */ + memset (cmdline, 0, SZ_CMD); + sprintf (cmdline, "session %s", args[0]); + } + + if (strcasecmp (proxy_host, vos_getLocalIP())) { + int nfiles = vos_uploadFiles (ipc_sock, cmdline); + vosDebug ("....sent %d data files....\n", nfiles); + } + + + if (strncmp (cmd, "?", 1) == 0 || strncmp (cmd, "help", 4) == 0) { + vos_cmdHelp (cmd); + return (0); + } + + /* Send the command string. + */ + vosDebug ("sending to proxy: '%s'\n", cmdline); + if (vos_sendCmd (ipc_sock, cmdline) == 0) { + vosDebug ("sending to proxy fails: '%s'\n", cmdline); + if (verbose) + fprintf (stderr, "Error writing command '%s'\n", cmdline); + + return (0); + + } else { + short nread, len; + + vosDebug ("reading ipc response ....\n"); + nread = vos_sockRead (ipc_sock, &len, sizeof (short)); + vosDebug ("ipc response len = %d....\n", len); + if (len > 0) { + char *res = calloc (1, (len+1)); + nread = vos_sockRead (ipc_sock, res, len); + vosDebug ("ipc response nread = %d....res = '%s'\n", nread, res); + if ((nread > 0 && strcmp (res, "OK") != 0) || verbose) + printf ("%s\n", res); + if (res) free ((void *) res); + } + return (1); + } + + return (0); +} + + +/** + * VOS_STARTPROXY -- Start the VOSAMP proxy process. + */ +static int +vos_startProxy (void) +{ + /* Start the keep-alive proxy server. + */ + if (keep_alive && in_parent && !have_dotfile) { + switch ( fork() ) { + case 0: /* start child proxy */ + vosDebug ("child pid\n"); + + /* Open server socket, read future input from socket. + */ + vosDebug ("child opening server port %d...\n", proxy_port); + if ((svr_sock = vos_openServerSocket (proxy_port)) < 0) { + fprintf (stderr, "Cannot open VOSAMP port %d\n", proxy_port); + if (have_dotfile) unlink (dotfile); + } + + FD_ZERO (&allset); + FD_SET (svr_sock, &allset); vos_setNonBlock (svr_sock); + vosDebug ("child svr_sock %d...\n", svr_sock); + + if (session) { + /* Open a client connection to the VOSAMP Session Manager. + */ + vosDebug ("initializing session '%s' on %s:%d\n", session, + session_host, session_port); + if ((session_sock = vos_openSession (session_host, + session_port, session)) < 2) { + vosDebug ("session open fails...\n"); + session_sock = 0; + session = NULL; + } else { + vosDebug ("child session sock %d...\n", session_sock); + FD_SET (session_sock, &allset); + vos_setNonBlock (session_sock); + sess_connected = 1; + } + } + + /* Now initialize the SAMP interface. + */ + vosDebug ("initializing SAMP connection\n"); +#ifdef HUB_BLOCKS + while (vos_sampInit () == 0) { + /* Wait for a Hub connection. + */ + if (debug || verbose) { + fprintf (stderr, "Waiting for Hub ...."); + sleep (VOS_HUBWAIT); + } + } +#else + hub_connected = vos_sampInit (); +#endif + + in_parent = 0; + vos_handleCmdInput (); + + /* Child never returns from this point ..... + */ + exit (0); + break; + + case -1: /* fork fails */ + if (verbose && in_parent) + fprintf (stderr, "%d proxy fork failure.\n", (int)getpid()); + break; + + default: /* parent exits */ + vosDebug ("parent pid\n"); + sleep (2); /* give child a chance to start */ + } + } + + return (0); +} + + +/** + * VOS_SENDCMD -- Send a SAMP_CMD to the specified socket. + */ +static int +vos_sendCmd (int sock, char *cmdline) +{ + char res[SZ_LINE]; + int nread = 0, nwrite = 0, len = (cmdline ? strlen (cmdline) : 0); + + + vosDebug ("sendCmd: '%s'\n", cmdline); + memset (res, 0, SZ_LINE); + + if (vos_sockWriteHdr (sock, len, NULL, SAMP_CMD, SAMP_NOTIFY, to)) { + vosDebug ("writing cmdline '%s' fd=%d\n", cmdline, sock); + nwrite = vos_sockWrite (sock, cmdline, len); + + /* See if we have a result returned to us. If so, it will be + * a character string we should just print out. + */ + if (session && sock != session_sock) { + vosDebug ("reading response fd=%d\n", sock); + nread = vos_sockRead (sock, &len, sizeof (int)); + if (len > 0) { + char *res = calloc (1, (len+1)); + + nread = vos_sockRead (sock, res, len); + if ((nread > 0 && strcmp (res, "OK") != 0) || verbose) + printf ("%s\n", res); + if (res) free ((void *) res); + } + } else + return (1); + } + + return (nread); +} + + +/** + * VOS_UPLOADFILES -- Upload any files on the commandline to the remote + * host. The remote client is responsible for rewriting the commandline + * as appropriate, our job here is to suss out which are the file arguments. + */ +int +vos_uploadFiles (int sock, char *cmdline) +{ + char *ip, *op, buf[SZ_BUF], fname[SZ_FNAME]; + int nfiles = 0; + + + for (ip=cmdline; *ip; ) { + memset (buf, 0, SZ_BUF); + memset (fname, 0, SZ_FNAME); + for (op=buf; *ip && !isspace(*ip); ) /* get token */ + *op++ = *ip++; + + /* Upload the file. If we have a file:// URL strip out the + * local pathname. Note that in this implementation we're + * limited to a single data file per-message. + */ + if (strncmp ("file://", buf, 7) == 0) { + strcpy (fname, &buf[7]); + if (access (fname, F_OK) < 0) /* file doesn't exist */ + return (-1); + } + if (access (buf, F_OK) == 0) + strcpy (fname, buf); + + if (fname[0]) { /* upload the file */ + vosDebug ("uploading file '%s'....\n", fname); + if (vos_sendFile (sock, fname, vos_getFName (fname)) != OK) + fprintf (stderr, "Error sending file '%s'\n", fname); + nfiles++; + } + + while (*ip && isspace (*ip)) /* skip whitespace */ + ip++; + } + + return (nfiles); +} + + +/** + * VOS_SENDFILE -- Send a file to a remote host. + */ +int +vos_sendFile (int sock, char *path, char *fname) +{ + char block[SZ_BLOCK]; + int fd, nread = 0, nleft = 0, size = 0, nb = 0; + struct stat fs; + + + if (access (path, R_OK) != 0 || stat (path, &fs) != 0) + return (ERR); + + size = fs.st_size; + nleft = size; + + if ((fd = open (path, O_RDONLY))) { + /* Send the header to pass the filename and size, then + * send the data itself. + */ + vos_sockWriteHdr (sock, size, fname, SAMP_DATA, 0, to); + while (nleft > 0) { + memset (block, 0, SZ_BLOCK); + nb = min (SZ_BLOCK, nleft); + + /* Read from the file, write it to the socket. + */ + vos_fileRead (fd, block, nb); + vos_sockWrite (sock, block, nb); + + nleft -= nb; + nread += nb; + } + close (fd); + } + + return (OK); +} + + +/** + * VOS_RECVFILE -- Receive a file of the specified size from a remote host. + */ +int +vos_recvFile (int sock, int size, char *fname) +{ + char block[SZ_BLOCK]; + int fd, nread = 0, nleft = size, nb = 0; + + + /* Read the file from the socket, write to the filename. + */ + vosDebug ("receiving file '%s'....%d\n", fname, size); + if ((fd = open (fname, O_WRONLY|O_CREAT, 0664))) { + while (nleft > 0) { + memset (block, 0, SZ_BLOCK); + nb = min (SZ_BLOCK, nleft); + + /* Read from the socket, write it to the file. + */ + vos_sockRead (sock, block, nb); + vos_fileWrite (fd, block, nb); + + nleft -= nb; + nread += nb; + } + close (fd); + } + + return (OK); +} + + +/** + * VOS_HANDLECMDINPUT -- Handle input from an input source. + */ +static void +vos_handleCmdInput () +{ + register int i, read_timeout = 0, rc; + char line[SZ_CMD]; + static char data_file[SZ_FNAME]; + + + memset (line, 0, SZ_CMD); + memset (data_file, 0, SZ_FNAME); + while (1) { /* loop until timeout */ + + /* Initialize the input file descriptor set and cmd buffer. + */ + memset (line, 0, SZ_CMD); + memset (cmd, 0, SZ_CMD); + for (i=0; i < MAX_ARGS; i++) + memset (args[i], 0, SZ_LINE); + + memcpy (&fds, &allset, sizeof(allset)); + if ((rc = select (8, &fds, NULL, NULL, (timeout ? &tm : NULL))) == 0) { + read_timeout++; /* input timeout */ + if (hub_connected && !samp_hubRunning()) { + hub_connected = 0; + } + if (!hub_connected && samp_hubRunning()) { + hub_connected = vos_sampInit(); +#ifdef HUB_TIMEOUT + } else { + unlink (dotfile); /* clean up the dotfile */ + vos_sampShutdown (); /* shutdown Hub connection */ + return; +#endif + } + continue; + + } else if (rc < 0) { /* Select error .... */ + vosDebug ("select error '%s'\n", strerror (errno)); + continue; + } + + + if (FD_ISSET(svr_sock, &fds)) { + int nbytes = 0, nread = 0, type = 0, mode = 0; + char fname[SZ_FNAME]; + + + /* Accept a connection on the proxy port from a cmdline client. + */ + vosDebug ("got input on server socket....\n"); + memset (fname, 0, SZ_FNAME); + + if ((ipc_sock = accept (svr_sock, NULL, NULL)) < 0) { + fprintf (stderr, "accept() errno %d: %s", + errno, strerror(errno)); + continue; + } + + if (vos_sockReadHdr (ipc_sock, &nbytes, fname, &type, &mode)) { + vosDebug ("server input: msgType = %s....\n", + vos_typeName (type)); + + if (strcasecmp (proxy_host, senderIP) && type == SAMP_DATA) { + if (vos_recvFile (ipc_sock, nbytes, fname) != OK) { + if (verbose || debug) + fprintf (stderr, "Error in recvFile '%s'\n", fname); + } + strcpy (data_file, fname); + + if (vos_sockReadHdr(ipc_sock, &nbytes, fname,&type,&mode)) { + nread = vos_sockRead (ipc_sock, line, nbytes); + vos_rewriteCmd (line, data_file); + } + memset (data_file, 0, SZ_FNAME); + + } else if (type == SAMP_CMD) { + nread = vos_sockRead (ipc_sock, line, nbytes); + vosDebug ("server cmd = '%s'....nr=%d nb=%d\n", + line, nread, nbytes); + if (data_file[0]) { + vos_rewriteCmd (line, data_file); + memset (data_file, 0, SZ_FNAME); + } + } else if (type == SAMP_RESULT) { + ; /* Not yet implemented */ + + } else if (type == SAMP_TEST) { + close (ipc_sock); /* Test connection, just ignore. */ + } + } + input_sock = ipc_sock; + + } else if (FD_ISSET(session_sock, &fds)) { + int nbytes = 0, nread = 0, type = 0, mode = 0; + + /* Accept a command from the session manager for forwarding. + */ + if (vos_sockReadHdr (session_sock, &nbytes, fname, &type, &mode)) { + vosDebug ("got input on session socket....\n"); + nread = vos_sockRead (session_sock, line, nbytes); + input_sock = session_sock; + + } else { + /* Session manager closed the socket, shut it down and + * disconnect. + */ + vosDebug ("Closing session socket....\n"); + FD_CLR (session_sock, &allset); + close (session_sock); + if (session) free ((void *) session); + session = NULL; + session_sock = 0; + continue; + } + + } else + vosDebug ("Ignoring input on other descriptor ...\n"); + + + /* Kill any trailing spaces and make sure we have an actual cmdline. + */ + if (isspace(line[strlen(line)-1])) + line[strlen(line)-1] = '\0'; + if (line[0] == '\0') + continue; + + + /* Check whether the command we want to process is directed to the + * proxy process itself. If so we process it locally rather than + * as a SAMP message for other clients. + */ + vosDebug ("handleCmd line: '%s'\n", line); + if (strncasecmp (line, "exec", 4) == 0 || + strncasecmp (line, "echo", 4) == 0) { + /* Special-case for exec/echo cmd to create single arg + */ + strncpy (cmd, line, 4); + sprintf (args[0], "%s", &line[5]); + numargs = 1; + vos_procCmd (sampH, to, cmd, args, numargs); + + } else if (strncasecmp (line, "status", 4) == 0) { + if (ipc_sock > 0) { + short slen, nwrite; + char buf[SZ_LINE]; + + memset (buf, 0, SZ_LINE); + sprintf (buf, "Status: SAMP Hub: %s ", + (hub_connected ? "ON " : "OFF")); + if (sess_connected) { + strcat (buf, "Session Mgr: ON (session='"); + strcat (buf, session); + strcat (buf, "')"); + } else + strcat (buf, "Session Mgr: OFF"); + + slen = strlen (buf); /* return result string */ + if (vos_sockWrite (ipc_sock, &slen, sizeof (short))) + nwrite = vos_sockWrite (ipc_sock, buf, slen); + + continue; + } + + } else if (strncasecmp (line, "quit", 4) == 0) { + /* Quit the proxy process and return. + */ + if (access (vos_dotFile(), F_OK) == 0) + unlink (vos_dotFile()); + vos_sampShutdown (); /* shutdown Hub connection */ + exit (0); + + } else if (strncasecmp (line, "list", 4) == 0) { + /* List the connected clients. + */ + verbose++, numargs=1; + vos_procCmd (sampH, to, "listClients", args, numargs); + + } else if (strncasecmp (line, "session", 7) == 0) { + /* Special commands for Session management. + */ + numargs = sscanf (line, "%s %s", cmd, args[0]); + + if (strcmp (args[0], "list") == 0) { + memset (args[0], 0, SZ_LINE); + strcpy (args[0], "listNodes"); + + if (session_sock == 0) { + fprintf (stderr, "Error: No session established\n"); + return; + } else { + verbose++; + numargs=1; + vos_procCmd (sampH, to, "listNodes", args, numargs); + } + + } else if (strncmp (args[0], "leave", 5) == 0) { + if (session_sock) + vos_closeSession (session_sock); + + } else { + /* Open a client connection to the VOSAMP Session Manager. + */ + if (vos_testClientSocket (session_host, session_port) < 0) { + fprintf (stderr, + "Error: Session manager not available at %s:%d\n", + session_host, session_port); + return; + } + vosDebug ("initializing session '%s' on %s:%d\n", args[0], + session_host, session_port); + session_sock = 0; + session = strdup (args[0]); + if ((session_sock = vos_openSession (session_host, + session_port, args[0])) < 2) { + vosDebug ("session open fails...\n"); + session_sock = 0, session = NULL; + } else { + vosDebug ("child session sock %d...\n", session_sock); + FD_SET (session_sock, &allset); + vos_setNonBlock (session_sock); + sess_connected = 1; + } + } + + } else { + /* Process the input command as a SAMP message. Only process + * the command if we're connected to a Hub + */ + if (hub_connected) { + numargs = sscanf (line, "%s %s %s %s %s %s %s %s %s", + cmd, args[0], args[1], args[2], args[3], + args[4], args[5], args[6], args[7]); + + vos_procCmd (sampH, to, cmd, args, numargs); + } + } + } + +#ifdef FOO + if (ipc_sock) + close (ipc_sock); /* close the socket descriptor */ +#endif +} + + +/** + * VOS_REWRITECMD -- Rewrite the command string with filename substitution. + */ +static void +vos_rewriteCmd (char *line, char *fname) +{ + char *ip, *op, buf[SZ_CMD], obuf[SZ_CMD]; + + memset (obuf, 0, SZ_CMD); + for (ip=line; *ip; ) { + memset (buf, 0, SZ_CMD); + for (op=buf; *ip && !isspace(*ip); ) /* get token */ + *op++ = *ip++; + + /* Replace file-URI and absolute paths with the replacement filename. + */ + if (strncmp ("file://", buf, 7) == 0 || buf[0] == '/') + strcat (obuf, fname); + else + strcat (obuf, buf); + + while (*ip && isspace (*ip)) /* skip whitespace */ + strncat (obuf, ip++, 1); + } + + memset (line, 0, SZ_CMD); + strcpy (line, obuf); +} + + +/** + * VOS_REWRITEURL -- Rwrite a URL argument so it is compatible with the + * session manager. Upload any local files if needed. + */ +static char * +vos_rewriteURL (char *in) +{ + static char out[SZ_URL], path[SZ_LINE], *fname; + char tmpfile[SZ_LINE]; + + + memset (path, 0, SZ_LINE); /* initialize */ + memset (tmpfile, 0, SZ_LINE); + memset (out, 0, SZ_URL); + + switch (vos_urlType (in)) { + case VOS_LOCALURL: + sprintf (tmpfile, "/tmp/%s", vos_getFName (in)); + vos_getURL (in, tmpfile); + strcpy (path, tmpfile); + break; + + case VOS_LOCALURI: + strcpy (path, &in[7]); + break; + + case VOS_LOCALFILE: + strcpy (path, in); + break; + + case VOS_REMOTE: + /* Nothing to do, simply return the string. + */ + return (in); + } + + /* Get the filename from the path. Format the new URL so that the + * session manager can easily rewrite it to use the smgr data space. + */ + fname = vos_getFName (path); + sprintf (out, "SESSION_URL/%s", fname); + + /* Send data to the session manager for storage as the 'fname'. The + * session manager will rewrite the URL. + */ + if (session_sock && vos_sendFile (session_sock, path, fname) != OK) + fprintf (stderr, "Error uploading file '%s'\n", in); + + return (out); +} + + +/** + * USAGE -- Print a task usage summary. + */ +static void +Usage (void) +{ + fprintf (stderr, + " Usage:\n" + "\n" + " %% vosamp [-hvd] [-t to] [-p pattern] [-f file] <cmd> [args ...]\n" + "\n" + " where:\n" + " <cmd> command to process\n" + " -%%,--test run unit tests\n" + " -h,--help print help summary\n" + " -d,--debug debug output\n" + " -v,--verbose verbose output\n" + " -q,--quiet suppress all output\n" + "\n" + " -i,--interact interactive mode\n" + " -m,--many handle multiple messages\n" + " -s,--sender <sender> handle only messages from <sender>\n" + "\n" + " -t,--to <to> send to specified app (or all)\n" + " -p,--pattern <pattern> message pattern: sync|async|notify\n" + " -f,--file <file> send all commands in the file\n" + " -n,--nokeepalive disable keep_alive feature\n" + "\n" + " -P,--proxy <IP> use specfied proxy IP\n" + " -T,--timeout <N> keepalive timeout\n" + "\n" + " -r,--return return result to API\n" + "\n" + " Commands:\n" + "\n" + " snoop print all received messages\n" + " send <mtype> [<args> ...] generalized <mtype> message send\n" + "\n" + " status print Hub availability\n" + " list list all registered clients\n" + " access <appName> print <appName> availability\n" + " handle <mtype> wait for <mtype> message\n" + "\n" + " exec <cmd> execute a client command\n" + " setenv <name> <value> set an environment value\n" + " getenv <name> get an environment value\n" + " setparam <name> <value> set a parameter value\n" + " getparam <name> get a parameter value\n" + "\n" + " load <url> load the image/table\n" + " loadImage <url> load the named image\n" + " loadVOTable <url> load the named VOTable\n" + " loadFITS <url> load the named FITS bintable\n" + " loadSpec <url> load the named spectrum\n" + " loadResource <ivorn> load the named VO Resource\n" + "\n" + " pointAt <ra> <dec> point at given coords\n" + " showRow [<url>] [<tblId>] <row> highlight specified row\n" + " selectRows [<url>] [<tblId>] <rows> select specified rows\n" + " bibcode <bibcode> load the bibcode\n" + "\n\n" + " Examples:\n\n" + " 1) Load a VOTable to Topcat:\n\n" + " %% vosamp load /path/example.xml\n" + " %% vosamp load http://foo.edu/example.xml\n" + " %% vosamp load http://foo.edu/query?RA=0.0&DEC=0.0&SR=0.1\n" + "\n" + " 2) Send a command string to IRAF:\n" + "\n" + " %% vosamp -t iraf exec 'display dev$pix 1'\n" + "\n" + " 3) List all clients in a SAMP desktop session:\n" + "\n" + " %% vosamp list\n" + "\n" + " 4) Check whether a Hub is available from a script:\n" + "\n" + " set isHub = `vosamp access Hub`\n" + " if ($isHub == \"no\") then\n" + " echo \"No Hub available, quitting .....\"\n" + " exit 1\n" + " else\n" + " ....do something....\n" + " endif\n" + "\n" + ); +} + + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + char *img = "http://iraf.noao.edu/votest/ypix.fits"; + char *vot = "http://iraf.noao.edu/votest/usno-b.xml"; + char *bin = "http://iraf.noao.edu/votest/usno-b.fits"; + + + if (access (input, F_OK) != 0) { + fprintf (stderr, "Error: cannot open input file '%s'\n", input); + return; + } + + vo_taskTest (task, "--help", NULL); + + vo_taskTest (task, "load", input, NULL); + vo_taskTest (task, "load", img, NULL); + vo_taskTest (task, "loadImage", img, NULL); + vo_taskTest (task, "load", vot, NULL); + vo_taskTest (task, "loadVOTable", vot, NULL); + vo_taskTest (task, "load", bin, NULL); + vo_taskTest (task, "loadFITS", bin, NULL); + + vo_taskTest (task, "access", "hub", NULL); + vo_taskTest (task, "list", NULL); + vo_taskTest (task, "load", input, NULL); + + vo_taskTestReport (self); +} + + +/** + * VOS_DOTFILE -- Create a pathname to the .vosamp file indicating a + * running local proxy server. + */ +static char * +vos_dotFile () +{ + static char dotfile[SZ_FNAME]; + static int initialized = 0; + + if (! initialized) { + char *home = NULL; + + if ((home = getenv ("HOME")) == NULL) + home = "./"; + memset (dotfile, 0, SZ_FNAME); + sprintf (dotfile, "%s/.vosamp", home); + } + initialized++; + + return (dotfile); +} + + +/** + * VOS_SAMPINIT -- Initialize the SAMP/Proxy interface connection. + */ +static int +vos_sampInit (void) +{ + FILE *df; + + + /* If there's no Hub running, don't bother .... + */ + if (!samp_hubRunning()) + return (0); + + /* Initialize the SAMP interface. + */ + sampH = sampInit ("vosamp", "VOClient SAMP Task"); +/* + if (samp_hubActive (sampH) == 0) { + vosDebug ("sampInit failed to connect ....\n"); + vos_sampShutdown (); + return (0); + } +*/ + + /* Set alternative messaging pattern if requested. Valid values are + * 'synch', 'asynch' or 'notify'. + */ + if (pattern) { + switch (tolower(pattern[0])) { + case 's': samp_setSyncMode (sampH); break; /* default */ + case 'a': samp_setASyncMode (sampH); break; + case 'n': samp_setNotifyMode (sampH); break; + default: + if (verbose) + fprintf (stderr, "Warning: Invalid pattern '%s'\n", pattern); + } + } else { + /* Use Synchronous mode by default so we don't exit before receiving + * the reply. Otherwise, we could cause an error in the recipient. + */ + samp_setSyncMode (sampH); + } + + /* If we're not sending to a specific client, disable the name mapping + * to speed up the connection. + if (strncmp (to, "all", 3) == 0) + samp_setOpt (sampH, "mapClients", 0); + */ + + samp_Metadata (sampH, "author.name", "Mike Fitzpatrick, NOAO"); + samp_Metadata (sampH, "author.email", "fitz@noao.edu"); + samp_Metadata (sampH, "samp.description.html", + "http://iraf.noao.edu/voclient/vosamp.html"); + samp_Metadata (sampH, "samp.icon.url", + "http://iraf.noao.edu/voclient/vao_icon.gif"); + + /* If we're in session mode, subscribe to all message types. The + * same handler is used to pass on the message to other clients in + * the session. + */ + if (session) + samp_Subscribe (sampH, "*", vos_sessionHandler); + + /* Register with the Hub and begin messaging. + */ + sampStartup (sampH); + + + /* Write the dotfile. + */ + if (!interact && (df = fopen (vos_dotFile(), "w+")) != (FILE *) NULL) { + fprintf (df, "%s %d %d %ld %s\n", vos_getLocalIP(), proxy_port, + (int) getpid(), (long) (time((time_t)0) + timeout), + (session ? session : "none")); + fclose (df); + } + + return (sampH); +} + + +/** + * VOS_SAMPSHUTDOWN -- Shutdown the SAMP/Proxy interface connection. + */ +static void +vos_sampShutdown (void) +{ + if (sampShutdown (sampH) < 0) /* clean up */ + fprintf (stderr, "SAMP shutdown fails\n"); + sampClose (sampH); +} + + +/** + * VOS_MSGHANDLER -- Incoming message handler. + */ +static void +vos_msgHandler (char *sender, char *mtype, char *msg_id, int params) +{ + vosDebug ("in vos_msgHandler.....\n"); + if (filt_sender && strcasecmp (filt_sender, sender)) + return; + + /* Either no filters were set, or the message is of the requested type, + * print the contents. + */ + if (!quiet) + vos_printMessage (mtype, samp_id2app (sampH, sender), params); + + if (!interact && !multiple) { /* Do a clean disconnect .... */ + if (sampShutdown (sampH) < 0) + fprintf (stderr, "SAMP shutdown fails\n"); + sampClose (sampH); + exit (0); + } +} + + +/** + * VOS_PRINTMESSAGE -- Print a received message to the stdout. + */ +static void +vos_printMessage (char *mtype, char *sender, Map map) +{ + int i, npars = samp_getMapSize (map); + char *key = NULL; + Map smap; + + + if (verbose) + printf ("sender: '%s'\t", sender); + printf ("%s", mtype); + + for (i=0; i < npars; i++) { + key = samp_getMapKey (map, i); + if (strncmp (key, "meta", 4) == 0 || strncmp (key, "sub", 3) == 0) { + smap = samp_getMapFromMap (map, key); + printf ("\n"); + samp_printMap (key, smap); + } else + printf ("\t%s=%s", key, samp_getMapVal (map, i)); + } + + printf ("\n"); +} + + +/** + * VOS_SESSIONHANDLER -- Generic session message-forwarding handler. + */ + +#define MTYPE(s) (strcasecmp(mtype,s)==0) + +static void +vos_sessionHandler (char *sender, char *mtype, char *msg_id, Map map) +{ + char sess_url[SZ_URL], sess_cmd[SZ_CMD], num[SZ_FNAME]; + char *tid = NULL, *imid = NULL, *url = NULL, *sid = NULL; + char *name = NULL, *value = NULL, *cmd = NULL, *bibcode = NULL; + char *key = NULL, *val = NULL; + int i, row = 0, rows = 0, len, nelem; + float ra, dec; + Map meta, ids; + + + if (!mtype) + return; + + memset (sess_url, 0, SZ_URL); + memset (sess_cmd, 0, SZ_CMD); + + /* + vosDebug ("sender: '%s' mtype: '%s' id: '%s'\n", sender, mtype, msg_id); + */ + + /* Process the mtype. + */ + if (MTYPE ("samp.app.ping")) { + ; /* FIXME -- no-op */ + + } else if (MTYPE ("samp.app.status")) { + ; /* FIXME -- no-op */ + + } else if (MTYPE ("table.load.fits")) { + tid = strdup (samp_getStringFromMap (map, "table-id")); + url = strdup (samp_getStringFromMap (map, "url")); + name = strdup (samp_getStringFromMap (map, "name")); + + sprintf (sess_cmd, "loadFITS %s %s", vos_rewriteURL(url), tid); + + + } else if (MTYPE ("table.load.votable")) { + /* Get parameters from the message Map. + */ + tid = strdup (samp_getStringFromMap (map, "table-id")); + url = strdup (samp_getStringFromMap (map, "url")); + name = strdup (samp_getStringFromMap (map, "name")); + + sprintf (sess_cmd, "loadVOTable %s %s", vos_rewriteURL(url), tid); + + + } else if (MTYPE ("table.highlight.row")) { + tid = strdup (samp_getStringFromMap (map, "table-id")); + url = strdup (samp_getStringFromMap (map, "url")); + row = samp_getIntFromMap (map, "row"); + + sprintf (sess_cmd, "showRow %s %d", vos_rewriteURL(url), row); + + + } else if (MTYPE ("image.load.fits")) { + imid = strdup (samp_getStringFromMap (map, "image-id")); + url = strdup (samp_getStringFromMap (map, "url")); + name = strdup (samp_getStringFromMap (map, "name")); + + sprintf (sess_cmd, "loadImage %s %s", vos_rewriteURL(url), imid); + + + } else if (MTYPE ("coord.pointAt.sky")) { + ra = samp_getFloatFromMap (map, "ra"); + dec = samp_getFloatFromMap (map, "dec"); + + sprintf (sess_cmd, "pointAt %g %g", ra, dec); + + + } else if (MTYPE ("client.cmd.exec")) { + cmd = strdup (samp_getStringFromMap (map, "cmd")); + + sprintf (sess_cmd, "exec %s", cmd); + + + } else if (MTYPE ("client.env.get")) { /** NYI **/ + name = strdup (samp_getStringFromMap (map, "name")); + + + } else if (MTYPE ("client.env.set")) { + name = strdup (samp_getStringFromMap (map, "name")); + value = strdup (samp_getStringFromMap (map, "value")); + + sprintf (sess_cmd, "setenv %s %s", name, value); + + + } else if (MTYPE ("client.param.get")) { /** NYI **/ + name = strdup (samp_getStringFromMap (map, "name")); + + + } else if (MTYPE ("client.param.set")) { + name = strdup (samp_getStringFromMap (map, "name")); + value = strdup (samp_getStringFromMap (map, "value")); + + sprintf (sess_cmd, "setparam %s %s", name, value); + + + } else if (MTYPE ("bibcode.load")) { + bibcode = strdup (samp_getStringFromMap (map, "bibcode")); + + sprintf (sess_cmd, "bibcode %s", bibcode); + + + } else if (MTYPE ("table.select.rowList")) { + tid = strdup (samp_getStringFromMap (map, "table-id")); + url = strdup (samp_getStringFromMap (map, "url")); + rows = samp_getListFromMap (map, "row-list"); + + sprintf (sess_cmd, "selectRows %s %s ", vos_rewriteURL(url), tid); + len = samp_listLen (rows); + for (i=0; i < len; i++) { + sprintf (num, "%d%c", samp_getIntFromList(rows,i), + (i < (len - 1) ? ',' : ' ')); + strcat (sess_cmd, num); + } + + + } else if (MTYPE ("spectrum.load.ssa-generic")) { + url = strdup (samp_getStringFromMap (map, "url")); + sid = strdup (samp_getStringFromMap (map, "spectrum-id")); + name = strdup (samp_getStringFromMap (map, "name")); + meta = samp_getMapFromMap (map, "meta"); + + sprintf (sess_cmd, "loadSpec %s %s %s", + vos_rewriteURL(url), (name ? name : " "), (sid ? sid : " ")); + + + } else if (MTYPE ("voresource.loadlist.*")) { /* NYI */ + name = strdup (samp_getStringFromMap (map, "name")); + ids = samp_getMapFromMap (map, "ids"); + + nelem = samp_getMapSize (ids); + for (i=0; i < nelem; i++) { + key = samp_getMapKey (ids, i); + val = samp_getMapVal (ids, i); + + /* Forward the resources individually. + */ + memset (sess_cmd, 0, SZ_CMD); + sprintf (sess_cmd, "loadResource %s", vos_rewriteURL(url)); + vos_forwardCmd (sess_cmd); + } + goto clean_up; + + + } else if (MTYPE ("samp.hub.disconnect")) { + ; /* ignore hub ejections */ + } else if (MTYPE ("samp.hub.event.subscriptions")) { + ; /* ignore client subscriptions */ + } else if (MTYPE ("samp.hub.unregister") || + MTYPE ("samp.hub.event.unregister")) { + ; /* ignore hub closures */ + + } else { + if (verbose && debug) + fprintf (stderr, "unknown mtype '%s'\n", mtype); + } + + + /* Forward the session command. + */ + vos_forwardCmd (sess_cmd); + + if (verbose && debug) + fprintf (stderr, "sessionHandler: cmdline = '%s'\n", sess_cmd); + + + /* Clean up. + */ +clean_up: + if (tid) free (tid); + if (url) free (url); + if (cmd) free (cmd); + if (sid) free (sid); + if (imid) free (imid); + if (name) free (name); + if (value) free (value); + if (bibcode) free (bibcode); +} + + +/** + * VOS_FORWARDCMD -- Forward a session command. + */ +static void +vos_forwardCmd (char *sess_cmd) +{ + int ssock = session_sock, len, nwrite; + + len = strlen (sess_cmd); + if (vos_sockWriteHdr (ssock, len, NULL, SAMP_CMD, SAMP_NOTIFY, to)) + nwrite = vos_sockWrite (ssock, sess_cmd, len); +} + + +/** + * VOS_PROCCMD -- Process the command and its arguments. + */ +static void +vos_procCmd (int sampH, char *to, char *cmd, char *args[], int numargs) +{ + int i, reslen = 0, stat = OK, ssock = session_sock; + char *result = NULL; + char buf[SZ_BUF]; + char sess_cmd[SZ_BUF]; + + + /* Print command help. + */ + if (!use_ipc) { + if (strncmp (cmd, "?", 1) == 0) { + Usage (); + return; + } + if (strncmp (args[0], "?", 1) == 0) { + vos_cmdHelp (cmd); + return; + } + } + + + /******************************************** + *** VOSAMP Custom Commands ** + ********************************************/ + memset (buf, 0, SZ_BUF); + memset (sess_cmd, 0, SZ_BUF); + + if (MATCH ("status")) { + stat = (sampH >= 0); + + } else if (MATCH ("handle")) { + int timeout = (vot_atoi (args[1]) == 0 ? 999999 : vot_atoi (args[1])); + + if (verbose) + fprintf (stderr, "Waiting for '%s' ....\n", args[0]); + if (*args[1]) + filt_sender = args[1]; + + samp_Subscribe (sampH, (filt_mtype = args[0]), vos_msgHandler); + samp_DeclareSubscriptions (sampH); + sleep (timeout); + + } else if (MATCH ("snoop")) { + /* Subscribe to all message types and install the snoop handler. + * Sleep forever so the handler can print anything it receives. + */ + multiple = 1; + samp_Subscribe (sampH, "*", vos_msgHandler); + samp_DeclareSubscriptions (sampH); + sleep (9999999); + + } else if (MATCH ("send")) { + if (strcasecmp (to, "all")) /* no recipient, use broadcast */ + samp_setASyncMode (sampH); + stat = samp_sendGeneric (sampH, to, args[0], &args[1]); + + } else if (MATCH ("echo")) { /* ECHO */ + if (!use_ipc) { + for (i=0; i < numargs; i++) + printf ("%s ", args[i]); + printf ("\n"); + } + + } else if (MATCH ("start")) { /* START */ + if (!use_ipc) + printf ("Starting SAMP interface .....\n"); + sampStartup (sampH); + + } else if (MATCH ("stop")) { /* STOP */ + if (!use_ipc) + printf ("Stopping SAMP interface .....\n"); + sampShutdown (sampH); + + } else if (MATCH ("help")) { /* HELP */ + Usage (); + + } else if (MATCH ("quit")) { /* QUIT */ + if (sampShutdown (sampH) < 0) { + if (!use_ipc) + fprintf (stderr, "Shutdown fails\n"); + } + sampClose (sampH); + unlink (vos_dotFile()); + exit (0); + + } else if (MATCH ("trace")) { /* TRACE */ + xml_trace++; + if (xml_trace % 2) + setenv ("XMLRPC_TRACE_XML", "1", 1); + else + unsetenv ("XMLRPC_TRACE_XML"); + + } else if (MATCH ("listNodes")) { /* LIST NODES */ + int type, mode, nbytes, len, nwrite; + char buf[SZ_BUF]; + + len = strlen ("list"); + if (vos_sockWriteHdr (ssock, len, "list", SAMP_CMD, SAMP_NOTIFY, to)) { + nwrite = vos_sockWrite (ssock, "list", len); + + memset (buf, 0, SZ_BUF); + if (vos_sockReadHdr (session_sock, &nbytes, NULL, &type, &mode)) + reslen = vos_sockRead (session_sock, buf, nbytes); + result = strdup (buf); + } + + } else if (MATCH ("listClients")) { /* LIST CLIENTS */ + char *clist = NULL; + + samp_mapClients (sampH); + clist = samp_getClients (sampH); + if (use_ipc) { + reslen = strlen (clist); + result = strdup (clist); + } else { + printf ("\nClients:\n%s\n", clist); + } + + + + /******************************************** + *** Hub Administrative Messages *** + ********************************************/ + } else if (MATCH ("ping")) { /* samp.app.ping */ + stat = samp_Ping (sampH, "Hub"); + + + + /******************************************** + *** Client Administrative Messages *** + ********************************************/ + } else if (MATCH ("ping")) { /* samp.app.ping */ + stat = samp_Ping (sampH, to); + + } else if (MATCH ("access")) { /* samp.app.ping */ + stat = samp_Ping (sampH, (to=args[0])); + if (use_ipc) { + result = strdup ((stat < 0 ? "no" : "yes")); + reslen = strlen (result); + return_stat = (stat < 0 ? ERR : OK); + } else { + printf ("%s\n", (stat < 0 ? "no" : "yes")); + return_stat = (stat < 0 ? ERR : OK); + } + + + + /******************************************** + *** Table/Image Load Message Types *** + ********************************************/ + /* image.load.fits */ + } else if (MATCH ("loadImage")) { + if ((stat = vos_invalidArg (numargs, args, 1, 1))) { + return_stat = ERR; + goto cmd_exit_; + } + stat = samp_imageLoadFITS (sampH, to, + vos_toURL (args[0]), /* URL/file */ + vos_optArg (args[1]), /* imgId */ + vos_optArg (args[2])); /* name */ + sprintf (sess_cmd, "loadImage %s %s", + vos_rewriteURL(vos_toURL (args[0])), vos_optArg (args[1])); + if (session && input_sock != session_sock) + vos_sendCmd (session_sock, sess_cmd); + + } else if (MATCH ("loadFITS")) { /* table.load.fits */ + if ((stat = vos_invalidArg (numargs, args, 1, 1))) { + return_stat = ERR; + goto cmd_exit_; + } + stat = samp_tableLoadFITS (sampH, to, + vos_toURL (args[0]), /* URL/file */ + vos_optArg (args[1]), /* tblId */ + vos_optArg (args[2])); /* name */ + sprintf (sess_cmd, "loadFITS %s %s", + vos_rewriteURL(vos_toURL (args[0])), vos_optArg (args[1])); + if (session && input_sock != session_sock) + vos_sendCmd (session_sock, sess_cmd); + + + } else if (MATCH ("loadVOTable")) { /* table.load.votable */ + if ((stat = vos_invalidArg (numargs, args, 1, 1))) { + return_stat = ERR; + goto cmd_exit_; + } + stat = samp_tableLoadVOTable (sampH, to, + vos_toURL (args[0]), /* URL/file */ + vos_optArg (args[1]), /* tblId */ + vos_optArg (args[2])); /* name */ + sprintf (sess_cmd, "loadVOTable %s %s", + vos_rewriteURL(vos_toURL (args[0])), vos_optArg (args[1])); + if (session && input_sock != session_sock) + vos_sendCmd (session_sock, sess_cmd); + + } else if (MATCH ("load")) { + char fname[SZ_LINE]; + extern int vot_fileType(); + + memset (fname, 0, SZ_LINE); + + if (strncmp (args[0], "http://", 7) == 0) { + strcpy (fname, "/tmp/vostmp"); /* temp download name */ + if (access (fname, F_OK) == 0) + unlink (fname); + if (vos_getURL (args[0], fname) <= 0) + fprintf (stderr, "Error accessing url '%s'\n", args[0]); + + } else if (strncmp (args[0], "file://", 7) == 0) { + strcpy (fname, &args[0][7]); + } else + strcpy (fname, args[0]); + + if (access (fname, F_OK) == 0) { + switch (vot_fileType (fname)) { + case VOT_FITS: + stat = samp_imageLoadFITS (sampH, to, + vos_toURL (fname), /* URL/file */ + vos_optArg (args[1]), /* imgId */ + vos_optArg (args[2])); /* name */ + sprintf (sess_cmd, "loadImage %s %s", + vos_rewriteURL(vos_toURL (fname)), vos_optArg (args[1])); + if (session && input_sock != session_sock) + vos_sendCmd (session_sock, sess_cmd); + break; + case VOT_VOTABLE: + stat = samp_tableLoadVOTable (sampH, to, + vos_toURL (fname), /* URL/file */ + vos_optArg (args[1]), /* tblId */ + vos_optArg (args[2])); /* name */ + sprintf (sess_cmd, "loadVOTable %s %s", + vos_rewriteURL(vos_toURL (fname)), vos_optArg (args[1])); + if (session && input_sock != session_sock) + vos_sendCmd (session_sock, sess_cmd); + break; + case VOT_FITS_SPEC: + break; + case VOT_VOTABLE_SPEC: + break; + default: + if (!use_ipc) + fprintf (stderr, + "Error: cannot determine file type of '%s'.\n", + args[0]); + } + } else + fprintf (stderr, "Error: cannot access '%s'.\n", fname); + + + + /******************************************** + *** Resource Message Types *** + ********************************************/ + } else if (MATCH ("loadResource")) { /* voresource.loadlist */ + if ((stat = vos_invalidArg (numargs, args, 1, 1))) { + return_stat = ERR; + goto cmd_exit_; + } + /* NYI */ + + + + /******************************************** + *** Utility Message Types *** + ********************************************/ + } else if (MATCH ("showRow")) { /* table.highlight.row */ + /* showRow <url> <row> [<id>] */ + stat = samp_tableHighlightRow (sampH, to, + vos_optArg (args[2]), /* table-id */ + vos_toURL (args[0]), /* URL/file */ + vot_atoi(args[1])); /* row */ + + } else if (MATCH ("selectRows")) { /* table.select.rowList */ + int nrows = 0; + int *rows = vos_toIntArray (args[2], &nrows); + + stat = samp_tableSelectRowList (sampH, to, + vos_optArg (args[0]), /* table-id */ + vos_toURL (args[1]), /* URL/file */ + rows, /* rows[] */ + nrows); /* row */ + + } else if (MATCH ("pointAt")) { /* coord.pointAt.sky */ + stat = samp_coordPointAtSky (sampH, to, + vot_atof (args[0]), /* RA */ + vot_atof (args[1])); /* Dec */ + + + /******************************************** + *** Spectrum Load Message Types *** + ********************************************/ + } else if (MATCH ("loadSpec")) { /* spectrum.load.ssa-generic */ + /* FIXME -- meta map not implemented */ + stat = samp_specLoadSSAGeneric (sampH, to, + vos_toURL (args[0]), /* URL */ + 0, /* Map meta */ /* NYI */ + vos_optArg (args[2]), /* spectrumId */ + vos_optArg (args[3])); /* name */ + + + /******************************************** + *** Bibcode Message Types *** + ********************************************/ + } else if (MATCH ("bibcode")) { /* bibcode.load */ + stat = samp_bibLoad (sampH, to, args[1]); + + + /******************************************** + *** VO/IRAF Message Types *** + ********************************************/ + } else if (MATCH ("exec")) { /* client.cmd.exec */ + samp_cmdExec (sampH, to, args[0]); + + } else if (MATCH ("getenv")) { /* client.env.get */ + char *v = samp_envGet (sampH, to, + args[0]); /* name */ + if (use_ipc) { + reslen = strlen (v); + result = strdup (v); + } else + printf ("%s\n", v); + if (v) free ((void *) v); + + } else if (MATCH ("setenv")) { /* client.env.set */ + stat = samp_envSet (sampH, to, + args[0], /* name */ + args[1]); /* value */ + + } else if (MATCH ("getparam")) { /* client.param.get */ + char *v = samp_paramGet (sampH, to, + args[0]); /* name */ + if (use_ipc) { + reslen = strlen (v); + result = strdup (v); + } else + printf ("%s\n", v); + if (v) free ((void *) v); + + } else if (MATCH ("setparam")) { /* client.param.set */ + stat = samp_paramSet (sampH, to, + args[0], /* name */ + args[1]); /* value */ + + + /******************************************** + *** Unknown Command *** + ********************************************/ + } else { + if (use_ipc) { + memset (buf, 0, SZ_BUF); + sprintf (buf, "Error: unknown command '%s'\n", cmd); + result = strdup (buf); + reslen = strlen (buf); + } else + fprintf (stderr, "Error: unknown command '%s'\n", cmd); + } + + + if (!quiet) { + if (!reslen) { + result = strdup ((stat < 0 ? "Error" : "OK")); + reslen = strlen (result); + return_stat = (stat < 0 ? ERR : OK); + } + } + vosDebug ("procCmd: reslen=%d result='%s'\n", reslen, result); + + + /* Return result to the remote caller. + */ +cmd_exit_: + if (ipc_sock > 0) { + int nwrite; + short slen = reslen; + + if (vos_sockWrite (ipc_sock, &slen, sizeof (short))) + nwrite = vos_sockWrite (ipc_sock, result, slen); + } + + if (result) free (result); +} + + +/** + * VOS_INVALIDARG -- Check arguments for validity. + */ +static int +vos_invalidArg (int argc, char *argv[], int nargs, int exist) +{ + int stat = 0; + + /* See if the number of args we have is less than what we require. + */ + if (argc < nargs) { + fprintf (stderr, "Error: invalid number of args for command '%s'\n", + cmd); + return ((stat = -1)); + } + + /* See whether we require the existance of the first argument. If this + * is a local file it must exist, assume URLs are valid. + */ + if (exist) { + if (!argv[0] || !argv[0][0]) + return ((stat = -1)); + if (strncmp ("http", argv[0], 4) && access (argv[0], R_OK)) { + fprintf (stderr, "Error: cannot access file '%s'\n", args[0]); + return ((stat = -1)); + } + } + + return (stat); +} + + +/** + * VOS_CMDHELP -- Print a command help summary for interactive mode. + */ +static void +vos_cmdHelp (char *cmd) +{ + if (MATCH ("status")) { + printf ("status\n"); + } else if (MATCH ("handle")) { + ; + } else if (MATCH ("snoop")) { + printf ("snoop\n"); + } else if (MATCH ("send")) { + ; + } else if (MATCH ("start")) { + printf ("start\n"); + } else if (MATCH ("stop")) { + printf ("stop\n"); + } else if (MATCH ("echo")) { + printf ("echo <text_string>\n"); + } else if (MATCH ("help")) { + printf ("help <cmd>\n"); + } else if (MATCH ("quit")) { + printf ("quit\n"); + } else if (MATCH ("trace")) { + printf ("trace\n"); + } else if (MATCH ("listClients")) { + printf ("listClients\n"); + } else if (MATCH ("ping")) { + printf ("ping <appName>\n"); + } else if (MATCH ("access")) { + printf ("access <appName>\n"); + + } else if (MATCH ("loadImage") || MATCH ("loadFITS")) { + printf ("loadImage <file | URL> [<table-id> [<name>]]\n"); + } else if (MATCH ("loadVOTable")) { + printf ("loadVOTable <file | URL> [<table-id> [<name>]]\n"); + } else if (MATCH ("loadResource")) { + ; + } else if (MATCH ("showRow")) { + printf ("showRow <table-id> <file | URL> <row>\n"); + } else if (MATCH ("selectRows")) { + printf ("selectRows <table-id> <file | URL> <rowList>\n"); + + } else if (MATCH ("pointAt")) { + printf ("pointAt <ra> <dec>\t# coords in decimal degrees\n"); + + } else if (MATCH ("loadSpec")) { + printf ("loadSpec <URL> <meta> [<spectrum-id> <name>]\n"); + } else if (MATCH ("bibcode")) { + printf ("bibcode <bibcode>\n"); + + } else if (MATCH ("exec")) { + printf ("exec <cmd_str>\n"); + } else if (MATCH ("getenv")) { + printf ("getenv <name>\n"); + } else if (MATCH ("setenv")) { + printf ("setenv <name> <value>\n"); + } else if (MATCH ("getparam")) { + printf ("getparam <name>\n"); + } else if (MATCH ("setparam")) { + printf ("setparam <name> <value>\n"); + } +} + + +/** + * VOSDEBUG -- Utility to print debug messages. + */ +static void +vosDebug (char *format, ...) +{ + va_list argp; + char buf[1024]; + extern char *vo_encodeString (); + + + if (!debug) + return; + + /* Format the message. + */ + memset (buf, 0, 1024); + va_start (argp, format); + vo_encodeString (buf, format, &argp); + va_end (argp); + + if (buf[strlen(buf)-1] != '\n') /* ensure a newline */ + strcat (buf, "\n"); + + fprintf (stderr, "[%d] %s", (int)getpid(), buf); +} + + + +/** + * VOS_OPENSESSION -- Open a connection to the VOSAMP Session Manager. + * + * @brief Open a connection to the VOSAMP Session Manager. + * @fn int vos_openSession (char *host, int port, char *session_name) + * + * @param host session manager host + * @param port session manager connection port + * @param name session name + * @return fd to the session socket + */ +int +vos_openSession (char *host, int port, char *session_name) +{ + int sock = 0, cb_sock = 0, cb_port = 0, nr, nw, len, ready = SESS_READY; + char cmd[SZ_LINE]; + + + /* Open a socket to the connection port. + */ + if ((sock = vos_openClientSocket (host, port, 1)) <= 0) + return (1); + + /* Read the callback port number. + */ + if ((nr = vos_sockRead (sock, &cb_port, sizeof (short))) != sizeof (short)) + return (1); + + /* Close the socket to the connection port. + */ + close (sock); + + /* Open a new connection to the callback port. + */ + if ((cb_sock = vos_openClientSocket (host, cb_port, 1)) <= 0) + return (1); + + /* Write the 'ready' code to the callback prot. + */ + nw = vos_sockWrite (cb_sock, &ready, sizeof (short)); + + + /* Send the 'connect' message to connect to the named session. The + * server will either create a new session or have us join an existing + * session created by another node. + */ + memset (cmd, 0, SZ_LINE); + sprintf (cmd, "connect %s", session_name); + len = strlen (cmd); + if (vos_sockWriteHdr (cb_sock, len, NULL, SAMP_CMD, SAMP_NOTIFY, "smgr")) + nw = vos_sockWrite (cb_sock, cmd, len); + + /* Return 0 if we can connect, 1 on err, or the callback descriptor. + */ + return (cb_sock); +} + + +/** + * VOS_CLOSESESSION -- Close the specified session connection. + * + * @brief Close the specified session connection. + * @fn int vos_closeSession (int sock) + * + * @param sock session socket fd + * @return 0 if cmd was sent, 1 otherwise + */ +int +vos_closeSession (int sock) +{ + if (vos_sockWriteHdr (sock, 0, NULL, SAMP_QUIT, SAMP_NOTIFY, "smgr")) + return (1); + return (0); +} + diff --git a/vendor/voclient/voapps/vosesame.c b/vendor/voclient/voapps/vosesame.c new file mode 100644 index 00000000..47a9c733 --- /dev/null +++ b/vendor/voclient/voapps/vosesame.c @@ -0,0 +1,680 @@ +/** + * VOSESAME -- Call the Sesame name resolver service on the specified target. + * + * Usage: vosesame [-adehntsv] [<objfile> | <target> [<target> ...]] + * + * -a,--all print all information about the object + * -d,--decimal print position in decimal degrees (default) + * -e,--errors print position errors + * -n,--name print object name + * -s,--sex print position as sexagesimal coordinates + * -t,--type print object type + * + * INPUT PARAMETERS + * -f,--force force new query (i.e. no cache) + * -o,--output=<file> specify output file + * -p,--pos comma-separated input position + * + * OUTPUT PARAMETERS + * -h,--help print help summary + * -q,--quiet quiet (no) output + * -v,--verbose verbose output + * -A,--ascii ASCII output (i.e. space-delimited) + * -C,--comma comma-delimited output + * -F,--format format output + * -H,--header print header + * -T,--tab tab-delimited output + * -I,--init_cache initialize the resolver cache directory + * + * Output is printed as whitespace delimited values in the same order + * in which the arguments appear. + * + * M. Fitzpatrick, NOAO, June 2007 + * + * @file vosesame.c + * @author Mike Fitzpatrick + * @date 6/23/07 + * @returns 0 if no error, 1 if an error occurs + * + * @brief Call the Sesame name resolver service on the specified target. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <getopt.h> +#include "VOClient.h" +#include "voApps.h" + + +/* Print field flags */ +#define F_ALL 0001 /* Print all fields */ +#define F_DEC 0002 /* Print decimal position */ +#define F_ERR 0004 /* Print position errors */ +#define F_NAM 0010 /* Print object name */ +#define F_TYP 0020 /* Print object type */ +#define F_SEX 0040 /* Print sexagesimal position */ + +#define MAX_FLAGS 16 +#define SZ_TARGET 64 /* size of target name */ + + +static int flags[MAX_FLAGS]; /* argv flags array */ +static int nflags = 0; /* number of flags */ +static int ntargets = 0; /* number of input targets */ +static int all_flags = 0; /* print all fields? */ + +static int format = TRUE; /* format the output? */ +static int header = FALSE; /* print a header? */ +static int invert = FALSE; /* invert to print non-matches */ +static int debug = FALSE; /* std debug flag */ +static int verbose = FALSE; /* std verbose flag */ +static int quiet = FALSE; /* suppress output flag */ +static int user_pos = TRUE; /* using user position? */ +static int status = OK; /* return status */ + +static char delim = ' '; /* output table delimiter */ +static char *output = (char *) NULL; + +static char *u_ra = (char *) NULL, /* user-defined position */ + *u_dec = (char *) NULL, + *sep = (char *) NULL; + +static FILE *out; + + +/* For getopt_long() option parsing. +*/ +/* Task specific option declarations. + */ +int vosesame (int argc, char **argv, size_t *len, void **result); + +static Task self = { "vosesame", vosesame, 0, 0, 0 }; + +static char *opts = "rh%aACdefFHno:p:qsTtvI"; +static struct option long_opts[] = { + { "return", 0, 0, 'r' }, /* task option */ + { "help", 2, 0, 'h' }, /* required */ + { "test", 2, 0, '%' }, /* required */ + + { "all", 2, 0, 'a' }, /* print all info about an object */ + { "ascii", 2, 0, 'A' }, /* ASCII (space-del) output */ + { "comma", 2, 0, 'C' }, /* comma-delimited output */ + { "decimal", 2, 0, 'd' }, /* print pos in dec. deg (def) */ + { "errors", 2, 0, 'e' }, /* print position errors */ + { "force", 2, 0, 'f' }, /* force new query (i.e. no cache) */ + { "format", 2, 0, 'F' }, /* format the output */ + { "header", 2, 0, 'H' }, /* print output header */ + { "name", 2, 0, 'n' }, /* print object name */ + { "output", 1, 0, 'o' }, /* specify output file */ + { "pos", 1, 0, 'p' }, /* comma-separated input position */ + { "quiet", 2, 0, 'q' }, /* quiet (i.e. no) output */ + { "sex", 2, 0, 's' }, /* print sexagesimal coordinates */ + { "tab", 2, 0, 'T' }, /* tab-delimited output */ + { "type", 2, 0, 't' }, /* print object type */ + { "verbose", 2, 0, 'v' }, /* verbose output */ + { "init_cache",2, 0, 'I' }, /* init resolver cache */ + { NULL, 0, 0, 0 } +}; + +static void Usage (void); +static void Tests (char *input); + + +extern int isDecimal(), isSexagesimal(); +extern float sexa(); +extern char *toSexa(); +extern double vot_atof (char *v); + +static int process_target (char *target); +static int print_result (char *target, Sesame sr); +static void print_header (void); +static void procUserCoord (char *u_ra, char *u_dec); + + +/** + * Application entry point. + */ +int +vosesame (int argc, char *argv[], size_t *reslen, void **result) +{ + char **pargv, optval[SZ_FNAME]; + register int ch=0, arg_index=1, narg=0; + int pos=0; + + + /* Process command line arguments and initialize. + */ + nflags = 0; + out = stdout; + *reslen = 0; + *result = NULL; + memset (flags, 0, MAX_FLAGS); + + pargv = vo_paramInit (argc, argv, opts, long_opts); + while ((ch = vo_paramNext (opts,long_opts,argc,pargv,optval,&pos)) != 0) { + if (ch > 0) { + switch (ch) { + case '%': Tests (optval); return (self.nfail); + case 'h': Usage(); return (OK); + case 'v': verbose++; quiet=0; break; + case 'q': quiet++; verbose=0; break; + + case 'a': all_flags++; break; + case 'i': invert++; break; + case 'd': flags[nflags++] = F_DEC; break; + case 'e': flags[nflags++] = F_ERR; break; + case 'n': flags[nflags++] = F_NAM; break; + case 's': flags[nflags++] = F_SEX; break; + case 't': flags[nflags++] = F_TYP; break; + + case 'p': + /* Check for a comma-separate position, break it up + ** if necessary. + */ + user_pos++; + if ((sep = (char *) strchr (optval, (int)','))) { + *sep = '\0'; + u_dec = strdup (++sep); + u_ra = strdup (optval); + } + if (debug) fprintf (stderr, "ra='%s' dec='%s'\n", u_ra,u_dec); + if (u_ra == NULL || u_dec == NULL) { + fprintf (stderr, "ERROR: Invalid '-p' syntax\n"); + return (ERR); + } + + /* Process a 'fake record' based on the position given. + ** Note this is done using the other options given up to + ** this point. + */ + procUserCoord (u_ra, u_dec); + break; + + case 'f': + if (voc_initVOClient("runid=voc.vosesame,use_cache=no") != OK) { + fprintf (stderr, "ERROR: cannot open VOClient\n"); + return (ERR); + } + break; + + case 'o': + output = strdup (optval); + if ((out = fopen (output, "w+")) == (FILE *)NULL) { + fprintf (stderr, "Cannot open file '%s'\n", output); + return (ERR); + } + break; + + case 'A': delim = ' '; break; + case 'C': delim = ',', format = 0; break; + case 'F': format++; break; + case 'H': header++; break; + case 'T': delim = '\t', format = 0; break; + + case 'I': /* FIXME */ + system ("/bin/rm -f ~/.voclient/cache/sesame/*"); + exit (0);; + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + /* Arguments without a leading '-' are assumed to be either + ** target names or @-files. We let the processing routine + ** figure out how to handle it. + */ + if ((status = process_target (optval)) != OK) { + if (!quiet) { + fprintf (stderr, "Warning: Cannot resolve target '%s'\n", + optval); + } + } + narg++; + } + arg_index++; + + /* Final error check for argument overflow -- should never happen. + if (arg_index > argc) + break; + */ + if (narg > MAX_FLAGS) { + fprintf (stderr, "ERROR: Too many arguments specified\n"); + return (1); + } + } + + + /* Process the arguments from the standard input. + */ + if (!ntargets) { + char *name = calloc (1, SZ_FNAME); + + while (fgets (name, SZ_FNAME, stdin)) { + name[strlen(name)-1] = '\0'; /* kill newline */ + if ((status += process_target (name)) != OK) { + if (!quiet) { + fprintf (stderr, + "Warning: cannot resolve target/access file '%s'\n", + name); + } + } else + ntargets++; + } + free (name); + } + + if (!ntargets) + fprintf (stderr, "Warning: No target name specified.\n"); + + if (u_ra) free ((void *) u_ra); + if (u_dec) free ((void *) u_dec); + if (output) free ((void *) output); + + if (out != stdout) + fclose (out); + + return ( status ); +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + printf ("\n\ + Usage: sesame [-adehntsv] [<objfile> | <target> [<target> ...]]\n\ + \n\ + -a,--all print all information about the object\n\ + -d,--decimal print position in decimal degrees (default)\n\ + -e,--errors print position errors\n\ + -n,--name print object name\n\ + -s,--sex print position as sexagesimal coordinates\n\ + -t,--type print object type\n\ + \n\ + INPUT PARAMETERS\n\ + -f,--force force new query (i.e. no cache)\n\ + -o,--output=<file> specify output file\n\ + -p,--pos comma-separated input position\n\ + \n\ + OUTPUT PARAMETERS\n\ + -h,--help print help summary\n\ + -q,--quiet quiet (no) output\n\ + -v,--verbose verbose output\n\ + -A,--ascii ASCII output (i.e. space-delimited)\n\ + -C,--comma comma-delimited output\n\ + -F,--format format output\n\ + -H,--header print header\n\ + -T,--tab tab-delimited output\n\ + \n\ + Output is printed as whitespace delimited values in the same order\n\ + in which the arguments appear.\n\ + \n\n"); + + printf ("\n\ + Examples:\n ---------\n\n\ + \n\ + 1) Print the coordinates of NGC4456 decimal degrees\n\ + \n\ + %% vosesame ngc4456\n\ + 186.968458 -30.097514\n\ + \n\ + 2) Print the sexagesimal coordinates of multiple objects\n\ + include the type:\n\ + \n\ + %% vosesame -st m31 m51 m99\n\ + 00:42:44.32 +41:16:07.5 LIN\n\ + 13:29:52.69 +47:11:42.9 Sy2\n\ + 12:18:49.62 +14:24:59.3 H2G\n\ + \n\ + 3) Print the decimal coordinates of those same objects listed\n\ + in the file 'myobjs.txt', output as CSV, include a header,\n\ + and print the id, coords, and type:\n\ + \n\ + %% vosesame -CHndt myobjs.txt\n\ + #Name,DRA,DDEC,Type,\n\ + m31,10.684708,41.268750,LIN\n\ + m51,202.469575,47.195258,Sy2\n\ + m99,184.706771,14.416489,H2G\n\ + : : : :\n\ + \n\ + 4) Print the sexagesimal and decimal values for multiple user coords:\n\ + \n\ + %% vosesame -sd -p 12:30:0.0,-45:00:0.0 -p 127.5,2.05\n\ + 12:30:00.0 -45:00:00.0 12.500000 -45.000000\n\ + 12:30:00.0 02:03:00.0 187.500000 2.050000\n\ + \n\ + "); + + printf ("\n\n"); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + vo_taskTest (task, "--help", NULL); + + vo_taskTestFile ("m31\nm51\nm99\n", "objs.txt"); + + vo_taskTest (task, "ngc4456", NULL); // Ex 1 + vo_taskTest (task, "-s", "ngc4456", NULL); // Ex 2 + vo_taskTest (task, "-st", "m31", "m51", "m99", NULL); // Ex 3 + vo_taskTest (task, "-CHndt", "objs.txt", NULL); // Ex 4 + vo_taskTest (task, "-sd", "-p", "12:30:00.0,-45:00:00.0", + "-p", "187.5,2.05", NULL); // Ex 5 + + if (access ("objs.txt", F_OK) == 0) unlink ("objs.txt"); + + vo_taskTestReport (self); +} + + + + +/************************************************************************ +** PROCUSERCOORD -- Process a user-specified coordinate. Generate a +** fake resolution record and output the requested values. +*/ +static void +procUserCoord (char *ra, char *dec) +{ + register int i; + char *fmt, sp; + char s_ra[SZ_FNAME], s_dec[SZ_FNAME], scoords[SZ_FNAME]; + double dra = 0.0, ddec = 0.0; + + + memset (s_ra, 0, SZ_FNAME); /* initialize */ + memset (s_dec, 0, SZ_FNAME); + memset (scoords, 0, SZ_FNAME); + + if (isDecimal (u_ra)) { + dra = vot_atof (u_ra); + sprintf (s_ra, "%s", toSexa (dra / 15.0)); + } else if (isSexagesimal (u_ra)) { + dra = sexa (u_ra); + strcpy (s_ra, u_ra); + } else { + fprintf (stderr, "Error in RA specification: '%s'\n", u_ra); + return; + } + + if (isDecimal (u_dec)) { + ddec = vot_atof (u_dec); + sprintf (s_dec, "%s", toSexa (ddec)); + } else if (isSexagesimal (u_dec)) { + ddec = sexa (u_dec); + strcpy (s_dec, u_dec); + } else { + fprintf (stderr, "Error in Dec specification: '%s'\n", u_dec); + return; + } + + sprintf (scoords, "%s %s", s_ra, s_dec); + + /* Set the default output if we got no commandline flags so far. + */ + ntargets++; + if (nflags == 0) + flags[nflags++] = F_DEC; + + + /* Print the output in the order specified by the flags. The exception + ** is the '-a' flag to print all information we have, but we do so in a + ** fixed format + */ + if (all_flags) { + if (format) + fmt = "%12.12s%c%23.23s%c%9.5f%c%9.5f%c0.0%c0.0%c%s\n"; + else + fmt = "%s%c%s%c%f%c%f%c0.0%c0.0%c%s\n"; + + fprintf (out, fmt, "UserCoord", delim, scoords, delim, + dra, delim, ddec, delim, delim, delim, "Unknown"); + + } else { + for (i=0; i < nflags; i++) { + sp = (i < (nflags - 1) ? delim : (char) 0); + switch (flags[i]) { + case F_DEC: + fprintf (out, "%f%c%f", (float)dra, delim, (float)ddec); + break; + case F_ERR: + fprintf (out, "0.0%c0.0", delim); + break; + case F_NAM: + fprintf (out, "UserCoord"); + break; + case F_TYP: + fprintf (out, "Unknown"); + break; + case F_SEX: + fprintf (out, "%s", scoords); + break; + } + if (sp) + fprintf (out, "%c", sp); + } + fprintf (out, "\n"); + } +} + + +/************************************************************************ +** PROCESS_TARGET -- Process a target name. +*/ +static int +process_target (char *target) +{ + int status; + char name[SZ_FNAME]; + extern char *vo_urlEncode(); + + + /* Do some error checking before we move on. + */ + if (target == (char *)NULL) { + fprintf (stderr, "ERROR: No target name or file specified.\n"); + return (ERR); + } + + /* Set the default output if we got no commandline flags so far. + */ + ntargets++; + if (nflags == 0) + flags[nflags++] = F_DEC; + + /* Now call the Resolver Service and summarize the results. + */ + if (target[0] == '@' || access (target, R_OK) == 0) { + char *fname = (target[0] == '@' ? &target[1] : &target[0]); + FILE *fd; + + + /* Open the @-file and process the contents. We assume there is + ** one target per line in the file, a target may contain spaces. + */ + if (access (fname, R_OK) != OK) { + fprintf (stderr, "Cannot access target file '%s'\n", fname); + return (ERR); + } else { + if ((fd = fopen (fname, "r")) == (FILE *)NULL) { + fprintf (stderr, "Cannot open target file '%s'\n", fname); + return (ERR); + } + } + + while (fgets (name, SZ_FNAME, fd)) { + name[strlen(name)-1] = '\0'; /* kill newline */ + status = print_result (name, voc_nameResolver (vo_urlEncode(name))); + } + fclose (fd); /* close the file and clean up */ + + } else { + /* Print the result for a single resolved target. + */ + status = print_result (target, voc_nameResolver (vo_urlEncode(target))); + } + + return (status); +} + + +/************************************************************************ +** PRINT_RESULT -- Print the result table in the requested format. +*/ +static int +print_result (char *target, Sesame sr) +{ + register int i, found; + char *type = NULL, *ip, *pos, sp; + double ra, dec, Era, Edec; + + + if (sr == 0) /* check for no match found */ + return (ERR); + + /* Fix the target name so spaces become underscores. + */ + for (ip=target; *ip; ip++) { + if (isspace (*ip) || *ip == '+') + *ip = ' '; + } + + /* First time through, check that the formatting makes sense and print + ** the header if requested. + */ + if (delim != ' ') + format = 0; + if (header && !invert) + print_header (); + + + /* Get the information for the object. + */ + pos = voc_resolverPos(sr); + if (delim != ' ' && ip) { + for (ip=pos; *ip; ip++) + *ip = (isspace(*ip) ? delim : *ip); + } + ra = voc_resolverRA(sr); + dec = voc_resolverDEC(sr); + Era = voc_resolverRAErr(sr); + Edec = voc_resolverDECErr(sr); + type = voc_resolverOtype(sr); + pos = voc_resolverPos(sr); + + found = 1; + if (ra == 0.0 && dec == 0.0 && Era == 0.0 && Edec == 0.0) + found = 0; + + + /* Return if we didn't get any results. + */ + if (!invert && !found) + return (ERR); + + /* Print the output in the order specified by the flags. The exception + ** is the '-a' flag to print all information we have, but we do so in a + ** fixed format + */ + if (all_flags) { + char *fmt; + + + if (format) + fmt = "%12.12s%c%23.23s%c%9.5f%c%9.5f%c%6.1f%c%6.1f%c%s\n"; + else + fmt = "%s%c%s%c%f%c%f%c%f%c%f%c%s\n"; + + if (!invert || (!found && invert)) { + fprintf (out, fmt, target, delim, pos, delim, + ra, delim, dec, delim, + Era, delim, Edec, delim, + type); + } + + } else if ((found && !invert) || (!found && invert)) { + for (i=0; i < nflags; i++) { + sp = (i < (nflags - 1) ? delim : (char) 0); + switch (flags[i]) { + case F_DEC: + fprintf (out, "%f%c%f", ra, delim, dec); + break; + case F_ERR: + fprintf (out, "%f%c%f", Era, delim, Edec); + break; + case F_NAM: + fprintf (out, "%s", target); + break; + case F_TYP: + fprintf (out, "%s", (type ? type : "Unknown")); + break; + case F_SEX: + for (ip=pos; *ip; ip++) { + if (isspace (*ip)) + *ip = delim; + } + fprintf (out, "%s", pos); + break; + } + if (sp) + fprintf (out, "%c", sp); + } + fprintf (out, "\n"); + } + + + return (OK); +} + + +/************************************************************************ +** PRINT_HEADER -- Put a header on the table. +*/ +static void +print_header () +{ + register int i; + char *fmt, sp; + + + if (all_flags) { + if (format) + fmt = "# %10.10s%c%-11.11s%c%-10.10s%c%-9.9s%c%-9.9s%c%-6.6s%c%-6.6s%c%s\n"; + else + fmt = "# %s%c%s%c%s%c%s%c%s%c%s%c%s%c%s\n"; + + fprintf (out, fmt, + "Name", delim, + (format ? " RA" : "RA"), delim, + (format ? " DEC" : "DEC"), delim, + (format ? " DRA" : "DRA"), delim, + (format ? " DDEC" : "DDEC"), delim, + "RAerr", delim, "DECerr", delim, + "Type", delim); + } else { + fprintf (out, "#"); + for (i=0; i < nflags; i++) { + sp = (((nflags-i) > 1) || nflags >= 1 ? delim : (char) 0); + switch (flags[i]) { + case F_DEC: fprintf (out, "DRA%cDDEC%c", sp, sp); break; + case F_ERR: fprintf (out, "RAerr%cDECerr%c", sp, sp); break; + case F_NAM: fprintf (out, "Name%c", sp); break; + case F_TYP: fprintf (out, "Type%c", sp); break; + case F_SEX: fprintf (out, "RA%cDEC%c", sp, sp); break; + } + } + fprintf (out, "\n"); + } + header = 0; /* disable the header */ +} diff --git a/vendor/voclient/voapps/vosession.c b/vendor/voclient/voapps/vosession.c new file mode 100644 index 00000000..958f1787 --- /dev/null +++ b/vendor/voclient/voapps/vosession.c @@ -0,0 +1,1278 @@ +/** + * VOSESSION -- Inter-Desktop Session Manager for the VOSAMP task. + * + * Usage: + * + * vosession [<opts>] + * + * Where + * -%,--test run unit tests + * -h,--help print help summary + * -d,--debug debug output + * -v,--verbose verbose output + * + * Subcommands: + * + * status print Hub availability + * list list all registered clients + * + * + * @file vosession.c + * @author Mike Fitzpatrick + * @date 6/03/12 + * + * @brief Session Manager for the VOSAMP task. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <fcntl.h> +#include <time.h> + +#include <netdb.h> +#include <sys/errno.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + + +#include "samp.h" /* LIBSAMP interface */ +#include "voApps.h" /* voApps interface */ + + +#define SZ_BUF 128 +#define SZ_MTYPE 64 +#define SZ_HOSTIP 16 + +#define MAX_ARGS 8 /* Max args in a command */ +#define MAX_SESSIONS 64 /* Max sessions to manage */ +#define MAX_PORTS 128 /* Max ports to manage */ + +#define SESS_SELWIDTH 32 /* select fd width */ +#define SESS_TIMEOUT 3600 /* 1-hr timeout */ +#define SESS_DISCONNECT 309 /* Session Mgr command timeout */ + +#define MATCH(s) (strcasecmp(cmd,s)==0) + + +/* Connected session client. + */ +typedef struct { + int sock; /* socket descriptor */ + int port; /* connection port */ + char hostIP[SZ_HOSTIP]; /* host IP address */ + char session[SZ_LINE]; /* session name */ + + void *back; /* linked-list back ptr */ + void *next; /* linked-list next ptr */ +} Node, *NodeP; + + +/* Session structure. + */ +typedef struct { + int nclients; /* number of clients */ + Node *clients; /* clients in session */ + char name[SZ_LINE]; /* session name */ + char dataCache[SZ_LINE]; /* path to local data cache */ + + int ncmds; /* Number of commands sent */ + int nfiles; /* Number of files uploaded */ + long nbytes; /* Number of files uploaded */ + time_t start_time; /* session start time */ + time_t end_time; /* session end time */ + time_t last_cmd; /* session last command */ + + void *back; /* linked-list back ptr */ + void *next; /* linked-list next ptr */ +} Session, *SessionP; + + +static int nSessions = 0; +static Session* sessHead = NULL; +static Session* sessTail = NULL; + +static int nClients = 0; +static Node* clientHead = NULL; +static Node* clientTail = NULL; + +static int verbose = FALSE; /* verbose output */ +static int debug = FALSE; /* verbose output */ +static int interactive = FALSE; /* interactive mode */ +static int xml_trace = FALSE; /* trace XML_RPC */ +static int timeout = SESS_TIMEOUT; /* select() doesn't timeout */ +static int svr_port = SESS_DEFPORT; /* connection port */ +static int selwidth = SESS_SELWIDTH;/* select() width */ + +static int keep_alive = TRUE; /* lingering connection */ +static int svr_sock = FALSE; /* server socket descriptor */ +static int cb_sock = 0; /* callback socket descriptor */ +static int cb_port = 0; /* callback port number */ +static int socks[MAX_PORTS]; /* available sockets */ + + +static char *to = NULL; /* message recipient */ +static char *session = NULL; /* session name */ +static char cmd[SZ_CMD]; /* command name */ +static char *args[MAX_ARGS]; /* command args buffer */ +static char data_file[SZ_URL]; /* uploaded data file */ + + +static fd_set allset, rfds; +static struct timeval tm; + + +#define NOAO +#ifdef NOAO +static char *sessionData = "/iraf/web/vosession"; +static char *sessionUrlBase = "http://iraf.noao.edu/vosession"; +#else +static char *sessionData = "/tmp/vosession"; +static char *sessionUrlBase = "file:///tmp/vosession"; +#endif +static char logfile[SZ_LINE]; +static char statfile[SZ_LINE]; + + + +/* Utility socket routines. + */ +extern int vos_openServerSocket (int port); +extern int vos_openClientSocket (char *host, int port, int retry); +extern int vos_sockRead (int fd, void *vptr, int nbytes); +extern int vos_sockWrite (int fd, void *vptr, int nbytes); +extern void vos_setNonBlock (int sock); +extern int vos_sockWriteHdr (int fd, int len, char *name, int type, + int mode, char *to); +extern int vos_sockReadHdr (int fd, int *len, char *name, int *type, + int *mode); +extern int vos_recvFile (int sock, int size, char *fname); +extern int vot_atoi (char *v); +extern char *vo_logtime (void); +extern char *vos_typeName (int type); + + + +/* Task specific option declarations. + */ +static char *opts = "h%:dikp:tuvS:T:"; +static struct option long_opts[] = { + { "help", 2, 0, 'h'}, /* required */ + { "test", 1, 0, '%'}, /* required */ + { "debug", 2, 0, 'd'}, /* debug */ + { "interactive", 2, 0, 'i'}, /* interactive mode */ + { "keepalive", 2, 0, 'k'}, /* keep connection */ + { "port", 1, 0, 'p'}, /* server port */ + { "trace", 2, 0, 't'}, /* trace cmds */ + { "url", 2, 0, 'u'}, /* upload data base URL */ + { "verbose", 2, 0, 'v'}, /* verbose */ + { "session", 1, 0, 'S'}, /* session name */ + { "timeout", 1, 0, 'T'}, /* connection timeout */ + { NULL, 0, 0, 0 } +}; + +static void Usage (void); +static void Tests (char *input); + + +static int sess_procCmd (int sock, int msgtype, int nbytes, char *fname); +static int sess_forwardMessage (int sender, char *msg); +static int sess_connectClient (int sock); +static int sess_disconnectClient (int sock); +static int sess_disconnectAllClients (void); +static int sess_joinSession (int sock, char *session_name); +static int sess_leaveSession (int sock, char *session_name); + +static Session *sess_newSession (char *name); +static int sess_freeSession (Session *s); + +static Node *sess_newNode (int sock); +static int sess_freeNode (Node *n); + +static Session *sess_byName (char *name); +static Session *sess_bySock (int sock); +static Node *sess_clientBySock (int sock); + +#ifdef SESSION_EXTRAS +static Session *sess_byPort (int port); +static Node *sess_clientByPort (int port); +static int sess_portToSock (int port); +#endif + +static int sess_newPort (void); +static int sess_freePort (int port); +static int sess_sockToPort (int sock); + +static char *sess_tok (char *str, int tok); +static void sess_rewriteCmd (char *line, char *session, char *fname); +static void sessLog (char *formtat, ...); +static void sess_writeStats (Session *session); +static void sess_printSessions (void); +static void sess_printClients (void); + + + + +/**************************************************************************** + * Program entry point. + ***************************************************************************/ +int +main (int argc, char **argv) +{ + char **pargv, optval[SZ_FNAME], ch; + int i, rc, pos = 0; + + + + /* Initialize. + */ + memset (logfile, 0, SZ_LINE); + memset (data_file, 0, SZ_URL); + svr_port = SESS_DEFPORT; + for (i=0; i < MAX_ARGS; i++) + args[i] = calloc (1, SZ_LINE); + + + /* Parse the argument list. + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + i = 0; + while ((ch = vo_paramNext (opts,long_opts,argc,pargv,optval,&pos)) != 0) { + i++; + if (ch > 0) { + switch (ch) { + case '%': Tests (optval); return (OK); + case 'h': Usage (); return (OK); + + case 'd': debug++; break; + case 'v': verbose++; break; + case 'k': keep_alive=0; break; + + case 'p': svr_port = vot_atoi(optval); break; + case 't': xml_trace=1; break; + + case 'S': session = strdup (optval); break; + case 'T': timeout = vot_atoi (optval); break; + + default: + fprintf (stderr, "Invalid option '%s'\n", optval); + return (1); + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + /* There is no other cmdline arg. + */ + fprintf (stderr, "Invalid option '%s'\n", argv[i]); + return (1); + } + } + + + /* Sanity checks. + */ + if (to == NULL) + to = strdup ("all"); + + /* Create the working session directory. + */ + if (access (sessionData, F_OK) < 0) { + if (mkdir (sessionData, 0755) < 0) { + fprintf (stderr, "Cannot create session directory '%s'\n", + sessionData); + return (1); + } + } + sprintf (logfile, "%s/Log", sessionData); + sprintf (statfile, "%s/Stats", sessionData); + + + /* Initialize the socket interface and timeouts. + */ + tm.tv_sec = timeout; + tm.tv_usec = 0; + + if ((svr_sock = vos_openServerSocket (svr_port)) < 0) { + sessLog ("Cannot open server connection port %d\n", svr_port); + return (1); + } else if (debug) { + sessLog ("=======================================\n"); + sessLog ("VOSession server started on port %4d\n", svr_port); + sessLog ("=======================================\n"); + } + + FD_ZERO (&allset); + FD_SET (svr_sock, &allset); + vos_setNonBlock (svr_sock); + if (interactive) { + FD_SET (fileno(stdin), &allset); + vos_setNonBlock (fileno(stdin)); + } + + + /* Begin processing. + */ + while (1) { + /* Initialize the input file descriptor set. + */ + memcpy (&rfds, &allset, sizeof(allset)); + rc = select (selwidth, &rfds, NULL, NULL, &tm); + if (rc == 0) { + time_t now = time (NULL); + Session *s = (Session *) NULL; + Node *n = (Node *) NULL; + + /* Send a disconnect to all subscribed clients that have been + * inactive for more than SESS_DISCONNECT seconds (1-hr); + */ + for (s=sessHead; s; s=s->next) { + if ((now - s->last_cmd) >= SESS_DISCONNECT) { + sessLog ("Session timeout for '%s'\n", s->name); + for (n=s->clients; n; n=n->next) { + sess_disconnectClient (n->sock); + sess_leaveSession (n->sock, s->name); + } + } + } + continue; + } + + /* Loop over the active descriptors to process input. + */ + for (i=0; i < selwidth+1; i++) { + if (FD_ISSET(i, &rfds)) { + if (i == svr_sock) { + /* Accept a new connection on the port. + */ + if (sess_connectClient (svr_sock) != 0) + sessLog ("Cannot connect Client: ", strerror(errno)); + + } else { + /* Handle input from existing client-node connection. + */ + int nread=0, nbytes=0, type=0, mode=0; + char fname[SZ_FNAME]; + + memset (fname, 0, SZ_FNAME); + if (debug > 1) sessLog ("Input on fd %d ....\n", i); + + /* Read the length of the message and type. + */ + nread = vos_sockReadHdr (i, &nbytes, fname, &type, &mode); + if (nread <= 0) { + /* Error on the socket or client closed connection. + */ + sess_disconnectClient (i); + } else { + /* Read the command. + */ + sess_procCmd (i, type, nbytes, fname); + } + } /* end is server socket */ + } /* end FD_ISSET */ + } /* end for */ + } /* end while */ + + + /* Clean up. Note, we should never actually get here.... + */ + if (to) free ((void *) to); + if (session) free ((void *) session); + sess_disconnectAllClients (); + + /* Close the the connection socket. + */ + if (svr_sock) + close (svr_sock); + + return (OK); +} + + + + +/*************************************************************************** +**** Client Handling Procedures **** +***************************************************************************/ + +/** + * SESS_PROCCMD -- Process a command message. + */ +static int +sess_procCmd (int sock, int msgtype, int nbytes, char *fname) +{ + + int i, len, nsent, type=0, mode=0, nread=0; + char line[SZ_LINE], path[SZ_LINE]; + Session *s = (Session *) sess_bySock (sock); + + + memset (line, 0, SZ_LINE); /* initialize */ + memset (path, 0, SZ_LINE); + + /* Read the command header. This will either be a SAMP_DATA + * message in which case we get a filename, or SAMP_CMD where + * we ignore the fname value and then read the command string. + */ + switch (msgtype) { + case SAMP_DATA: + sprintf (path, "%s/%s", s->dataCache, fname); + + if (vos_recvFile (sock, nbytes, path) != OK) { + if (debug) + sessLog ("Error receiving file '%s'\n", fname); + } + strcpy (data_file, fname); + + vos_sockReadHdr (sock, &nbytes, fname, &type, &mode); + nread = vos_sockRead (sock, line, nbytes); + if (debug) sessLog ("SAMP_DATA: '%s' '%s'\n", line, fname); + sess_rewriteCmd (line, s->name, data_file); + memset (data_file, 0, SZ_FNAME); + + s->nfiles++; + s->nbytes += nbytes; + + /* Forward to other connected clients. + */ + s->ncmds++; + s->last_cmd = time (NULL); + nsent = sess_forwardMessage (sock, line); + if (debug) + sessLog ("Forwarded to %d clients in '%s'\n", nsent, s->name); + + break; + + case SAMP_CMD: + case SAMP_RELAY: + nread = vos_sockRead (sock, line, nbytes); + + if (debug) + sessLog ("%s[%d][%s]: '%s'\n", vos_typeName (msgtype), nread, + (s ? s->name : ""), line); + if (s && line[0] && data_file[0]) { + sess_rewriteCmd (line, s->name, data_file); + memset (data_file, 0, SZ_FNAME); + } + + if (strncasecmp (line, "quit", 4) == 0) { /* QUIT */ + sess_disconnectClient (sock); + + } else if (strncasecmp (line, "list", 4) == 0) { /* LIST */ + Node *n = (Node *) NULL; + char buf[(4*SZ_LINE)], line[SZ_LINE]; + + memset (buf, 0, (4 * SZ_LINE)); + sprintf (buf, "Clients in session '%s':\n", s->name); + for (i=0,n=clientHead; n; n=n->next,i++) { + memset (line, 0, SZ_LINE); + sprintf (line, " [%d]: host: %16.16s port: %d\n", + i, n->hostIP, n->port); + strcat (buf, line); + } + + /* Write the result string back to the client. + */ + len = strlen (buf); + if (vos_sockWriteHdr (sock, len, NULL, SAMP_RESULT, + SAMP_NOTIFY, "all")) + nread = vos_sockWrite (sock, buf, strlen (buf)); + + } else if (strncasecmp (line, "connect", 4) == 0) { /* JOIN */ + sess_joinSession (sock, sess_tok (line, 2)); + + } else if (strncasecmp (line, "leave", 4) == 0) { /* LEAVE */ + sess_leaveSession (sock, s->name); + + } else { /* ELSE .... */ + if (line[0] && msgtype == SAMP_CMD) { + nsent = sess_forwardMessage (sock, line); + if (debug) + sessLog ("Forward to %d clients in '%s'\n", nsent, s->name); + } + } + if (s) { + s->ncmds++; + s->last_cmd = time (NULL); + } + break; + + case SAMP_RESULT: + if (debug) + sessLog ("%s[%s]: '%s'\n", vos_typeName (msgtype), + (s ? s->name : ""), " "); + break; /* Not yet implemented */ + + case SAMP_QUIT: + sess_leaveSession (sock, NULL); + sess_disconnectClient (sock); + break; + + default: + sessLog ("cmd: '%s'\n", cmd); + } + + return (0); +} + + +/** + * SESS_FORWARDMESSAGE -- Forward the message to all clients in the session + * other than the one which originated it. + */ +static int +sess_forwardMessage (int sender, char *msg) +{ + Session *s = sess_bySock (sender); + Node *n = (Node *) NULL; + int len, nw, sock, nsent = 0; + + + for (n=s->clients; n; n=n->next) { + sock = n->sock; + if (sock != sender) { + if (debug) fprintf (stderr, "forward to '%s'\n", n->hostIP); + len = strlen (msg); + if (vos_sockWriteHdr (sock, len, NULL, SAMP_RELAY, 0, "all")) + nw = vos_sockWrite (sock, msg, len); + nsent++; + } + } + + return (nsent); +} + + +/** + * SESS_CONNECTCLIENT -- Connect a client on the named socket. + */ +static int +sess_connectClient (int sock) +{ + int new, nr; + short ready, sport; + struct sockaddr_in client; + size_t size = sizeof (client); + char sname[SZ_LINE]; + + + memset (sname, 0, SZ_LINE); + + if ((new = accept (sock, (struct sockaddr *) &client, + (socklen_t *) &size)) < 0) { + sessLog ("svr_sock accept() errno %d: %s", errno, strerror(errno)); + + } else { + char *host = inet_ntoa (client.sin_addr); + int port = ntohs (client.sin_port); + Node *node = (Node *) NULL; + + + /* Attach the client to the list of connected hosts. + */ + node = sess_newNode (new); + node->port = port; + node->sock = new; + strcpy (node->hostIP, host); + if (clientHead) { + clientTail->next = node; + clientTail = node; + } else { + clientHead = clientTail = node; + } + nClients++; + + /* Open new server connection and send the callback + * port number over the connection. After that, we + * don't need the initial connection so release it. + */ + cb_port = sport = sess_newPort (); + cb_sock = vos_openServerSocket (cb_port); + if (debug) + sessLog ("Connect from host:%s, port:%d, fd:%d, cb_port: %d\n", + host, port, new, cb_port); + vos_sockWrite (new, &sport, sizeof(short)); + cb_port = sport; + close (new); + + /* Waiting for callback to connect. + */ + if ((new = accept (cb_sock, NULL, NULL)) < 0) + sessLog ("cb_sock accept() errno %d: %s", errno, strerror(errno)); + vos_setNonBlock (new); + + /* Wait for the callback ready message so we know + * we are connected to the client. + */ + nr = vos_sockRead (new, &ready, sizeof(short)); + if (ready == SESS_READY) { +#ifdef READ_CONNECT + int nbytes=0, type=0, mode=0; + + /* Read the session name. + */ + vos_sockReadHdr (new, &nbytes, NULL, &type, &mode); + nr = vos_sockRead (new, sname, nbytes); + + if (verbose) + sessLog ("Connect host %s:%d\n", + inet_ntoa(client.sin_addr), ntohs(client.sin_port), sname); + strcpy (node->session, sname); +#else + if (verbose) + sessLog ("Connect host %s:%d\n", + inet_ntoa (client.sin_addr), ntohs (client.sin_port)); +#endif + } + + + /* Add the client socket fd to the master set of + * active descriptors. + */ + FD_SET (new, &allset); + } + + return (0); +} + + +/** + * SESS_DISCONNECTCLIENT -- Shutdown client on the named socket. + */ +static int +sess_disconnectClient (int sock) +{ + Node *client = sess_clientBySock (sock); + + sessLog ("Disconnecting client %d....\n", sock); + FD_CLR (sock, &allset); + close (sock); + + sess_freeNode (client); + sess_freePort (client->port); + + return (0); +} + + +/** + * SESS_DISCONNECTALLCLIENTS -- Shutdown all connected clients + */ +static int +sess_disconnectAllClients () +{ + Session *s = (Session *) NULL; + Node *n = (Node *) NULL; + + /* Loop over all the session and their client lists and disconnect + * the client. We do it here rather than following the client list + * since we'll also clean up the data cache when the session is closed. + */ + for (s=sessHead; s; s=s->next) { + for (n=s->clients; n; n=n->next) { + if (debug) + sessLog ("Disconnecting host %s on port %d from '%s'\n", + n->hostIP, n->port, s->name); + + sess_leaveSession (n->sock, s->name); + } + } + return (0); +} + + + + +/*************************************************************************** +**** Session Procedures **** +***************************************************************************/ + +/** + * SESS_JOINSESSION -- Join (or create) a session. + */ +static int +sess_joinSession (int sock, char *session_name) +{ + Session *s = (Session *) NULL; + Node *n = (Node *) NULL; + int found = 0; + + + if (sessHead) { + s = sess_byName (session_name); + if (s == (Session *) NULL) { + /* Name not found, create a new session pointer. + */ + s = sess_newSession (session_name); + sessTail->next = s; + sessTail = s; + nSessions++; + } + + } else { + /* No active sessions, create one. + */ + s = sessHead = sessTail = sess_newSession (session_name); + + /* Create the working session directory. + */ + sprintf (s->dataCache, "%s/%s", sessionData, session_name); + if (access (s->dataCache, F_OK) < 0) { + if (debug) sessLog ("Making session cache directory '%s'\n", + s->dataCache); + if (mkdir (s->dataCache, 0755) < 0) { + fprintf (stderr, "Cannot create session cache directory '%s'\n", + s->dataCache); + return (1); + } + } + nSessions++; + } + + /* Now attach the node the session list of clients, both the master + * client list and the client list in each session. + */ + for (n=clientHead; n; n=n->next) { /* master client list */ + if (sock == n->sock) + strcpy (n->session, session_name); + } + found = 0; + for (n=s->clients; n && n->next; n=n->next) { + if (n->sock == sock) { /* skip to end of client list */ + /* client is already in session. + */ + found++; + } + } + + /* Add to client list if it isn't already found. + */ + if (!found) { + if (n) { + n->next = sess_newNode (sock); + strcpy (n->session, session_name); + } else { + s->clients = sess_newNode (sock); + strcpy (s->clients->session, session_name); + } + s->nclients++; + } + + if (debug > 1) { sess_printSessions (); sess_printClients (); } + return (0); +} + + +/** + * SESS_LEAVESESSION -- Leave an open session. + */ +static int +sess_leaveSession (int sock, char *session_name) +{ + Session *s = (Session *) NULL; + int port = sess_sockToPort (sock); + + + s = (session_name ? sess_byName (session_name) : sess_bySock (sock)); + if (s) { + Node *n = s->clients; + + while (n && n->port != port) + n = n->next; + + if (n) { + sessLog ("%s leaves session '%s'\n", n->hostIP, s->name); + sess_freeNode (n); + s->nclients--; + } + + if (s->nclients == 0) { + /* Remove the working session directory and its contents. + */ + if (access (s->dataCache, F_OK) == 0) { + char cmd[SZ_LINE]; + + memset (cmd, 0, SZ_LINE); + sprintf (cmd, "/bin/rm -rf %s", s->dataCache); + if (debug) sessLog ("Removing session cache directory '%s'\n", + s->dataCache); + + system (cmd); /* FIXME */ + } + sess_freeSession (s); + } + } + + if (debug > 1) sess_printSessions (); + return (0); +} + + +/** + * SESS_BYNAME - Find a Session pointer by name. + */ +static Session * +sess_byName (char *name) +{ + Session *s = (Session *) NULL; + + for (s=sessHead; s; s=s->next) + if (strcasecmp (name, s->name) == 0) + break; + + return (s); +} + + +/** + * SESS_BYSOCK - Find a Session socket descriptor. + */ +static Session * +sess_bySock (int sock) +{ + Session *s = (Session *) NULL; + Node *n = (Node *) NULL; + + for (n=clientHead; n; n=n->next) { + if (sock == n->sock) + return (sess_byName (n->session)); + } + return (s); +} + + +/** + * SESS_CLIENTBYSOCK - Find a Node pointer by socket fd. + */ +static Node * +sess_clientBySock (int sock) +{ + Node *n = (Node *) NULL; + + for (n=clientHead; n; n=n->next) { + if (n->sock == sock) + return (n); + } + + return ((Node *) NULL); +} + + +/** + * SESS_SOCKTOPORT - Lookup a port number by the socket fd. + */ +static int +sess_sockToPort (int sock) +{ + Node *n = (Node *) NULL; + + for (n=clientHead; n; n=n->next) { + if (n->sock == sock) + return (n->port); + } + + return (-1); +} + + +#ifdef SESSION_EXTRAS +/** + * SESS_CLIENTBYPORT - Find a Node pointer by port number. + */ +static Node * +sess_clientByPort (int port) +{ + Node *n = (Node *) NULL; + + for (n=clientHead; n; n=n->next) { + if (n->port == port) + return (n); + } + + return ((Node *) NULL); +} + + +/** + * SESS_BYPORT - Find a Session port number. + */ +static Session * +sess_byPort (int port) +{ + Session *s = (Session *) NULL; + Node *n = (Node *) NULL; + + for (n=clientHead; n; n=n->next) { + if (port == n->port) + return (sess_byName (n->session)); + } + return (s); +} + + +/** + * SESS_PORTTOSOCK - Lookup a socket fd by the client port number. + */ +static int +sess_portToSock (int port) +{ + Node *n = clientHead; + + for (n=clientHead; n; n=n->next) + if (n->port == port) + return (n->sock); + + return (-1); +} +#endif + + +/** + * SESS_NEWSESSION - Create a new Session structure. + */ +static Session * +sess_newSession (char *name) +{ + Session *s = (Session *) calloc (1, sizeof (Session)); + + strcpy (s->name, name); + s->start_time = time (NULL); + return (s); +} + + +/** + * SESS_FREESESSION - Release a Session structure. + */ +static int +sess_freeSession (Session *s) +{ + Session *back = (Session *) (s ? s->back : NULL); + Session *next = (Session *) (s ? s->next : NULL); + + if (s == sessHead) + sessHead = (Session *) next; /* head of the list */ + else if (s->next == (Session *) NULL) + sessHead = (Session *) back; /* tail of the list */ + else + back->next = (void *) s->next; /* middle of the list */ + + if (s->nclients == 0) { + fprintf (stderr, "Free up session resources for '%s'\n", s->name); + } + nSessions--; + + s->end_time = time (NULL); + + sess_writeStats (s); /* log the session stats */ + + free ((void *) s); + if (debug > 1) sess_printSessions (); + return (0); +} + + +/** + * SESS_NEWNODE - Create a new Node structure. + */ +static Node * +sess_newNode (int sock) +{ + Node *n = (Node *) calloc (1, sizeof (Node)); + Node *client = sess_clientBySock (sock); + + if (client) { + n->sock = client->sock; + n->port = client->port; + strcpy (n->hostIP, client->hostIP); + } + + return (n); +} + + +/** + * SESS_FREENODE - Free a Node structure. + */ +static int +sess_freeNode (Node *node) +{ + if (node->back) { + Node *back = node->back; + back->next = node->next; + } + if (node->next) { + Node *next = node->next; + next->back = node->back; + } + + free ((void *) node); + return (0); +} + + +/** + * SESS_PRINTSESSIONS - Utility to print the session list. + */ +static void +sess_printSessions (void) +{ + Session *s = sessHead; + Node *n = (Node *) NULL; + int i, j; + + if (!s) { + fprintf (stderr, "No active sessions\n"); + + } else { + for (s=sessHead,i=0; s; s=s->next, i++) { + fprintf (stderr, "Session[%d]: session '%s' has %d client%c\n", + i, s->name, s->nclients, (s->nclients > 1 ? 's':' ')); + for (n=sessHead->clients,j=0; n; n=n->next, j++) { + fprintf (stderr, " Client[%d]: port: %d host: %s\n", + j, n->port, n->hostIP); + } + } + } +} + + +/** + * SESS_PRINTCLIENTS - Utility to print the client list. + */ +static void +sess_printClients (void) +{ + Node *n = (Node *) NULL; + int i; + + for (n=clientHead,i=0; n; n=n->next, i++) { + fprintf (stderr, "Client[%d]: port:%d sock:%d host:%s session:%s\n", + i, n->port, n->sock, n->hostIP, n->session); + } +} + + +/*************************************************************************** +**** Utility Procedures **** +***************************************************************************/ + +/** + * SESS_WRITESTATS -- Log the sessions statistics. + */ +static void +sess_writeStats (Session *s) +{ + FILE *fd; + char buf[SZ_LINE]; + double nsec; + + + if (s) { + memset (buf, 0, SZ_LINE); + nsec = (s->end_time - s->start_time); + sprintf (buf, + "%s %16.16s ncmds: %d nfiles: %d nbytes: %ld time: %6.1f min\n", + vo_logtime(), s->name, s->ncmds, s->nfiles, s->nbytes, (nsec/60.)); + + if ((fd = fopen (statfile, "w+"))) { + if (debug) + sessLog ("%s", buf); + fprintf (fd, "%s", buf); + fflush (fd); fclose (fd); + } + } else + sessLog ("Error: writeStats gets null session"); +} + + +/** + * SESSLOG -- Print a message to the logfile. + */ +static void +sessLog (char *format, ...) +{ + FILE *fd; + va_list argp; + char *buf = calloc (1, 1024); + char *tstr = NULL; + int len=0; + extern char *vo_encodeString (); + + + /* Format the message. + */ + va_start (argp, format); + vo_encodeString (buf, format, &argp); + va_end (argp); + + len = strlen (buf); /* ensure a newline */ + if (buf[len-1] != '\n') + strcat (buf, "\n"); + + + /* Log the message. + */ + tstr = vo_logtime (); + if (logfile[0] == '-' || strcasecmp (logfile, "stdout") == 0) { + printf ("%s %s", tstr, buf); + + } else { + if ((fd = fopen (logfile, "w+"))) { + if (debug) + fprintf (stderr, "%s %s", tstr, buf); + fprintf (fd, "%s %s", tstr, buf); + fflush (fd); fclose (fd); + } + } + + free ((void *) buf); +} + + +/** + * SESS_NEWPORT -- Get an open socket/port entry. + */ +static int +sess_newPort () +{ + int i, p; + + for (i=0; i < MAX_PORTS; i++) { + p = svr_port + i + 3; + if (socks[i] == 0) { + socks[i] = p; + return (p); + } + } + + sessLog ("Error: No available client ports.\n"); + return (-1); +} + + +/** + * SESS_FREEPORT -- Free a socket/port entry. + */ +static int +sess_freePort (int port) +{ + int i, p; + + for (i=0; i < MAX_PORTS; i++) { + p = svr_port + i + 3; + if (p == port) { + close (socks[p]); + socks[i] = 0; + } + } + + return (0); +} + + +/** + * SESS_TOK -- Get the specified (1-indexed) w/s delimited token from str. + */ +static char * +sess_tok (char *str, int toknum) +{ + register int i; + static char tok[SZ_FNAME]; + char *ip = str, *op = tok; + + + memset (tok, 0, SZ_FNAME); /* initialize */ + + for (i=1; i < toknum; i++) { /* skip ahead to the token */ + while (!isspace ((int) (*ip)) && *ip) ip++; + while ( isspace ((int) (*ip)) && *ip) ip++; + } + + do { + *op++ = *ip++; + } while (!isspace ((int) (*ip)) && *ip); /* copy the token */ + + return (tok); +} + + +/** + * SESS_REWRITECMD -- Rewrite the command string with filename substitution. + */ +static void +sess_rewriteCmd (char *line, char *session, char *fname) +{ + char *ip, *op, buf[SZ_LINE], obuf[SZ_LINE], name[SZ_FNAME]; + + + memset (obuf, 0, SZ_LINE); + for (ip=line; *ip; ) { + memset (buf, 0, SZ_LINE); + memset (name, 0, SZ_FNAME); + + for (op=buf; *ip && !isspace(*ip); ) /* get token */ + *op++ = *ip++; + +#ifdef USE_FILE_URI + /* Replace file-URI and absolute paths with the replacement filename. + */ + if (strncmp ("file://", buf, 7) == 0 || buf[0] == '/') + strcat (obuf, fname); + else + strcat (obuf, buf); +#else + /* Replace 'SESSION_URL' with the session dataCache URL. + */ + if (strncmp ("SESSION_URL", buf, 11) == 0) { + strcpy (name, (buf[11] ? &buf[12] : fname)); + sprintf (buf, "%s/%s/%s", sessionUrlBase, session, name); + } + strcat (obuf, buf); +#endif + + while (*ip && isspace (*ip)) /* skip whitespace */ + strncat (obuf, ip++, 1); + } + + memset (line, 0, SZ_LINE); + strcpy (line, obuf); +} + + + +/** + * USAGE -- Print a task usage summary. + */ +static void +Usage (void) +{ + fprintf (stderr, + " Usage:\n" + "\n" + " %% vosession [-hvd] [-p <port>]\n" + "\n" + " where <cmd> command to process\n" + " -h print help summary\n" + " -v verbose output\n" + " -d debug output\n" + "\n" + " -p <port> server port\n" + "\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + ; /* no-op */ +} diff --git a/vendor/voclient/voapps/vosloanspec.c b/vendor/voclient/voapps/vosloanspec.c new file mode 100644 index 00000000..70fcfbe9 --- /dev/null +++ b/vendor/voclient/voapps/vosloanspec.c @@ -0,0 +1,765 @@ +/* + * VOTSLOANSPEC -- Query and access spectra from SDSS/BOSS + * + * Usage: + * vosloanspec [<opts>] <obj> | {<ra> <dec>} | {<ra> <dec> <radius>} + * + * where + * -%%,--test Run unit tests + * -h,--help This message + * -d,--debug Debug Flag + * -v,--verbose Verbose Flag + * -r,--return=<obj> Return object + * + * -P,--pos=<ra>,<dec> Set query position (dec degrees) + * -R,--release=<rel> Data release (dr8/dr9/current) (def=current) + * -s,--size=<radius> Set query radius (dec degrees) + * -t,--type=<type> Object type (all|galaxy|qso|star) + * -z,--redshift=<zrange> Select by redshift range string(s) + * + * -c,--count Return only count of results + * -m,--meta Print result position metadata + * -D,--delete Delete spectra after printing metadata + * -l,--limit=<N> Limit to top <N> results + * -u,--urls Get urls to spectra + * + * -S,--samp Broadcase urls to SAMP (as spectrum) + * -T,--table Broadcase urls as VOTable message + * -N,--num=<N> Number of download threads + * + * -f,--file=<file> Input file + * -b,--base=<file> Base filename + * -O,--output=<file> Output file + * -o,--object=<obj> Object name + * + * Interface based on API at: http://api.sdss3.org/index.html + * + * + * @file vosloanspec.c + * @author Mike Fitzpatrick + * @date 9/93/12 + * + * @brief Query and access spectra from SDSS/BOSS + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <ctype.h> +#include <pthread.h> +#include <errno.h> +#include <sys/stat.h> + +#include "samp.h" +#include "VOClient.h" +#include "voApps.h" + + +#define SZ_RESBUF 8192 +#define SZ_URL 1024 + +#define MAX_THREADS 64 +#define DEF_THREADS 12 +#define MAX_DOWNLOADS 65537 + +#define NEXTARG(a) strdup(optval);argnum++; + + +static int verbose = FALSE; /* verbose flag */ +static int debug = FALSE; /* debug flag */ +static int count = FALSE; /* count results */ +static int urls = FALSE; /* get URLs to data? */ +static int asSpec = TRUE; /* SAMP as Spectrum (or Table)? */ +static int nthreads = DEF_THREADS; /* Number of downlaod threads */ +static int ndownloads = 0; /* Number of file downloads */ +static int specnum = 0; /* spectrum number */ + +static int have_infile = FALSE; /* have input file? */ +static int do_return = FALSE; /* return result? */ +static int do_samp = FALSE; /* broadcast SAMP result? */ +static int do_meta = FALSE; /* get spectrum metadata? */ +static int do_delete = FALSE; /* delete files after metadata? */ + +static char *pos = NULL; /* position string */ +static char *release = NULL; /* data release */ +static char *limit = NULL; /* limit results */ +static char *size = NULL; /* search radius */ +static char *type = NULL; /* spectrum type */ +static char *redshift = NULL; /* redshift range */ +static char *iname = NULL; /* input position name */ +static char *oname = NULL; /* output name */ +static char *object = NULL; /* object name */ +static char *basename = NULL; /* base filename */ + +static double ra = -999.9; /* RA query position */ +static double dec = -999.9; /* Dec query position */ +static double rad = 0.25; /* query size (deg) */ + +static char ra_str[SZ_FNAME]; +static char dec_str[SZ_FNAME]; +static char rad_str[SZ_FNAME]; + +#ifdef USE_RESBUF +static char *resbuf; /* result buffer */ +#endif + +char url[SZ_URL]; +char *query_base = "http://api.sdss3.org/spectrumQuery?"; +char *spec_base = "http://api.sdss3.org/spectrum?"; + + +typedef struct { + char url[SZ_URL]; /* access URL */ + char fname[SZ_URL]; /* local filename */ + int tnum; /* worker thread number */ +} Acref, *AcrefP; + +Acref aclist[MAX_DOWNLOADS]; /* access list */ + + +/* Task specific option declarations. + */ +int vosloanspec (int argc, char **argv, size_t *len, void **result); + +static Task self = { "vosloanspec", vosloanspec, 0, 0, 0 }; +static char *opts = "%hrvdDP:N:R:STs:t:z:cl:uf:o:bm"; +static struct option long_opts[] = { + { "test", 2, 0, '%'}, /* required */ + { "help", 2, 0, 'h'}, /* required */ + { "verbose", 2, 0, 'v'}, /* verbose flag */ + { "debug", 2, 0, 'd'}, /* debug flag */ + { "return", 1, 0, 'r'}, /* task return option */ + + { "pos", 1, 0, 'P'}, /* position param */ + { "release", 1, 0, 'R'}, /* data release */ + { "table", 2, 0, 'T'}, /* data release */ + { "size", 1, 0, 's'}, /* search radius */ + { "type", 1, 0, 't'}, /* spectra type */ + { "redshift", 1, 0, 'z'}, /* redshift range */ + + { "count", 2, 0, 'c'}, /* count results */ + { "meta", 2, 0, 'm'}, /* count results */ + { "limit", 1, 0, 'l'}, /* limit results */ + { "urls", 2, 0, 'u'}, /* get urls */ + { "samp", 2, 0, 'S'}, /* broadcast SAMP */ + { "num", 1, 0, 'N'}, /* num downloads */ + { "delete", 2, 0, 'D'}, /* num downloads */ + + { "file", 1, 0, 'f'}, /* input file */ + { "output", 1, 0, 'O'}, /* output file */ + { "object", 1, 0, 'o'}, /* object name */ + { "base", 1, 0, 'b'}, /* base filename */ + { NULL, 0, 0, 0 } +}; + + +static void Usage (void); +static void Tests (char *input); +static int vos_getCountValue (char *fname); +static int vos_sampInit (void); +static char *vos_getURLValues (char *fname); +static void vot_procAclist (void); +static void vot_procMeta (void); +static void *vot_getAclist (void *arg); + +extern int vos_getURL (); +extern int vot_atoi (char *v); +extern double vot_atof (char *v); +extern char *vot_mktemp (); + +extern int vosesame (int argc, char **argv, size_t *len, void **result); +extern char *vo_urlEncode (char *target); + + + +/** + * Application entry point. + */ +int +vosloanspec (int argc, char **argv, size_t *reslen, void **result) +{ + int apos, argnum = 0, status = OK; + FILE *fd = (FILE *) NULL; + char **pargv, optval[SZ_FNAME], ch, *urlList = NULL;; + char *tmp = vot_mktemp ("vosloan"); + + + /* Initialize. + */ + oname = NULL; + iname = NULL; + *reslen = 0; + *result = NULL; + + ra = -999.9; + dec = -999.9; + memset (ra_str, 0, SZ_FNAME); + memset (dec_str, 0, SZ_FNAME); + memset (rad_str, 0, SZ_FNAME); + memset (url, 0, SZ_URL); /* initialize the query URL */ + strcpy (url, query_base); + strcpy (rad_str, "900"); /* 0.25 deg default */ + + asSpec = TRUE; + do_samp = FALSE; + do_meta = FALSE; + do_delete = FALSE; + + pos = NULL; /* position string */ + release = NULL; /* data release */ + limit = NULL; /* limit results */ + size = NULL; /* search radius */ + type = NULL; /* spectrum type */ + redshift = NULL; /* redshift range */ + iname = NULL; /* input position name */ + oname = NULL; /* output name */ + object = NULL; /* object name */ + basename = NULL; /* base filename */ + + + /* Parse the argument list. + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + while ((ch = vo_paramNext (opts,long_opts,argc,pargv,optval,&apos)) != 0) { + argnum++; + if (ch > 0) { + switch (ch) { + case '%': Tests (NULL); return (self.nfail); + case 'h': Usage (); return (OK); + + case 'v': verbose++; break; + case 'd': debug++; break; + case 'r': do_return++; break; /* FIX */ + + case 'N': nthreads = vot_atoi (optval); argnum++; break; + case 'P': pos = NEXTARG (optval); break; + case 'R': release = NEXTARG (optval); break; + case 's': size = NEXTARG (optval); + sprintf (rad_str, "%g", (rad = vot_atof(size) * 3600.)); + break; + case 't': type = NEXTARG (optval); break; + case 'z': redshift = NEXTARG (optval); break; + + case 'c': count++; break; + case 'm': do_meta++; break; + case 'u': urls++; break; + case 'S': do_samp++; break; + case 'D': do_delete++; break; + case 'T': asSpec--; break; + case 'l': limit = NEXTARG (optval); break; + + case 'f': iname = NEXTARG (optval); /* NYI */ + have_infile++; + break; + case 'O': oname = NEXTARG (optval); break; + case 'o': object = NEXTARG (optval); + if (argv[argnum]) { + Sesame sr; + char *opts = "runid=voc.vosloanspec,use_cache=no"; + + if (voc_initVOClient (opts) != OK) { + fprintf (stderr,"ERROR: can't open VOClient\n"); + return (ERR); + } + sr = voc_nameResolver (vo_urlEncode (argv[argnum])); + if (sr == 0) { + fprintf (stderr,"ERROR: can't resolve '%s'\n", + argv[argnum]); + return (ERR); + } else { + sprintf (ra_str, "%f", + (ra=voc_resolverRA (sr))); + sprintf (dec_str, "%f", + (dec=voc_resolverDEC (sr))); + } + } + break; + case 'b': basename = NEXTARG (optval); break; + default: + fprintf (stderr, "Invalid option '%s'\n", optval); + return (1); + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + + switch (argc - argnum) { + case -1: /* obj */ + argnum--; + case 0: /* obj */ + argnum--; + case 1: /* obj */ + /* resolve object pos + */ + if (argv[argnum]) { + Sesame sr; + char *opts = "runid=voc.vosloanspec,use_cache=no"; + + if (voc_initVOClient (opts) != OK) { + fprintf (stderr, "ERROR: cannot open VOClient\n"); + return (ERR); + } + sr = voc_nameResolver (vo_urlEncode (argv[argnum])); + if (sr == 0) { + fprintf (stderr,"ERROR: can't resolve '%s'\n", + argv[argnum]); + return (ERR); + } + sprintf (ra_str, "%f", (ra = voc_resolverRA (sr))); + sprintf (dec_str, "%f", (dec = voc_resolverDEC (sr))); + } + break; + case 2: /* ra dec */ + ra = vot_atof (argv[argnum]); + dec = vot_atof (argv[argnum+1]); + strcpy (ra_str, argv[argnum]); + strcpy (dec_str, argv[argnum+1]); + break; + case 3: /* ra dec rad */ + ra = vot_atof (argv[argnum]); + dec = vot_atof (argv[argnum+1]); + rad = vot_atof (argv[argnum+2]); + strcpy (ra_str, argv[argnum]); + strcpy (dec_str, argv[argnum+1]); + strcpy (rad_str, argv[argnum+2]); + break; + } + break; + } + } + + if (debug) + fprintf (stderr, "ra = %f dec = %f rad = %f\n", ra, dec, rad); + + /* Sanity checks + */ + if (iname == NULL) iname = strdup ("stdin"); + if (oname == NULL) oname = strdup ("stdout"); + if (strcmp (iname, "-") == 0) { free (iname), iname = strdup ("stdin"); } + if (strcmp (oname, "-") == 0) { free (oname), oname = strdup ("stdout"); } + + if (rad > 36000) /* enforce max query size of 10 deg */ + rad = 36000; + + + /* Append parameters to the base URL based on the cmdline options. We + * parse the positions/sizes and deal with files below. + */ + if (limit) strcat (url, "&limit="), strcat (url, limit); + if (type) strcat (url, "&class="), strcat (url, type); + if (release) strcat (url, "&release="), strcat (url, release); + if (redshift) strcat (url, "&redshift="), strcat (url, redshift); + if (count) strcat (url, "&count"); + strcat (url, "&urls"); /* always get URLS */ + + if (ra != -999.9) + strcat (url, "&ra="), strcat (url, ra_str), strcat (url,"d");; + if (dec != -999.9) + strcat (url, "&dec="), strcat (url, dec_str); + strcat (url, "&radius="); strcat (url, rad_str); + + if (debug) + fprintf (stderr, "url[0] = %s\n", url); + + + /* Access the query URL, saving the result to the named filed. We'll + * process the options on the resulting file. + */ + if (vos_getURL (url, tmp) >= 0) { + if (count) { + printf ("%d\n", vos_getCountValue (tmp)); + + } else if (urls) { + printf ("%s", (urlList= vos_getURLValues (tmp))); + + } else { + char *url = NULL, *base = NULL, tok[SZ_URL], fname[SZ_FNAME]; + int sampH = vos_sampInit (); + + url = urlList = vos_getURLValues (tmp); + memset (tok, 0, SZ_URL); + base = (basename ? basename : "sdss"); + + if (do_samp) { + if (verbose) + fprintf (stderr, "Initializing SAMP ....\n"); + sampH = sampInit ("vosloanspec", "VOClient SDSS Task"); + } + + for (specnum=0; *url && sscanf (url, "%s", tok); specnum++) { + memset (fname, 0, SZ_FNAME); + sprintf (fname, "%s%04d.fits", base, specnum); + + if (do_samp) { + /* Broadcast URL as a SAMP message, either as a bintable + * or an ssa-generic spectrum. + */ + if (sampH) { + int stat = -1; + + if (verbose) + fprintf (stderr, "Loading '%s' ....\n", tok); + if (asSpec) { + stat = samp_specLoadSSAGeneric (sampH, "all", + tok, /* URL */ + 0, /* Map meta */ /* NYI */ + fname, /* spectrumId */ + fname); /* name */ + } else { + stat = samp_tableLoadFITS (sampH, "all", + tok, /* URL/file */ + fname, /* tblId */ + fname); /* name */ + } + } + + } else { + /* Download URL to a local file. + */ + aclist[specnum].tnum = ((nthreads == 1) ? 0 : + (specnum % nthreads)); + strcpy (aclist[specnum].url, tok); + strcpy (aclist[specnum].fname, fname); + ndownloads++; + } + + url += strlen (tok) + 1; + memset (tok, 0, SZ_URL); + } + + /* Process the access list (downloads) and metadata request. + */ + if (ndownloads) { + vot_procAclist (); + if (do_meta) + vot_procMeta (); + } + + if (do_samp && sampH) + sampClose (sampH); + } + } else + status = ERR; + + + /* Clean up. + */ + if (fd != stdout) + fclose (fd); + if (urlList) + free ((void *) urlList); + + if (pos) free (pos); + if (type) free (type); + if (size) free (size); + if (limit) free (limit); + if (iname) free (iname); + if (oname) free (oname); + if (object) free (object); + if (release) free (release); + if (redshift) free (redshift); + if (basename) free (basename); + + vo_paramFree (argc, pargv); + + return (status); +} + + +/** + * VOT_PROCACLIST -- Process the access list. + */ +static void +vot_procAclist (void) +{ + /* Spawn the worker threads. + */ + int rc = 0, tc = 0, status = 0, tnum[MAX_THREADS]; + pthread_attr_t attr; /* thread attributes */ + pthread_t thread[MAX_THREADS]; + + + /* Initialize the service processing thread attributes and run 'em. + */ + pthread_attr_init (&attr); + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE); + + for (tc=0; tc < nthreads; tc++) { + tnum[tc] = tc; + if ((rc = pthread_create (&thread[tc], &attr, vot_getAclist, + (void *)&tnum[tc]))) { + fprintf (stderr, "ERROR: pthread_create() fails, code=%d\n", + rc); + return; + } + } + + /* Free attribute and wait for the threads to complete. + */ + pthread_attr_destroy (&attr); + for (tc=0; tc < nthreads; tc++) { + if ((rc = pthread_join (thread[tc], (void **)&status)) ) { + if (rc != ESRCH) { + fprintf (stderr, + "ERROR: pthread_join() fails, code=%d status=%d\n", + rc, status); + return; + } + } + } + + if (verbose) + fprintf (stderr, "Downloaded %d files -- complete\n", ndownloads); +} + + +/** + * VOT_GETACLIST -- Download all the files for the specified thread. + */ +static void * +vot_getAclist (void *arg) +{ + register int i; + int threadNum = 0; + + + if (arg) { + threadNum = *(int *)arg; + + for (i=0; i < ndownloads; i++) { + if (aclist[i].tnum == threadNum) { + if (verbose) + fprintf (stderr, "%s -> %s\n", + aclist[i].fname, aclist[i].url); + vos_getURL (aclist[i].url, aclist[i].fname); + } + } + } + return ((void *) NULL); +} + + +/** + * VOT_PROCMETA -- Process the metadata request. + */ +static void +vot_procMeta (void) +{ + int i, fd, nread; + char rec[(4 * 2880)]; + + for (i=0; i < ndownloads; i++) { + if (access (aclist[i].fname, R_OK) == 0) { + if ((fd = open (aclist[i].fname, O_RDONLY)) >= 0) { + nread = read (fd, rec, (size_t) (4 * 2880)); + printf ("%s\t", aclist[i].fname); + printf ("%11.6f\t", atof (strstr (rec, "PLUG_RA") + 11)); + printf ("%12.6f\n", atof (strstr (rec, "PLUG_DEC") + 11)); + close (fd); + + if (do_delete) + unlink (aclist[i].fname); + } + } + } +} + + +/** + * VOS_GETCOUNTVALUE -- Get the value from a count request. + */ +static int +vos_getCountValue (char *fname) +{ + char buf[SZ_LINE], *line; + FILE *fd; + + if (fname && (fd = fopen (fname, "r"))) { + memset (buf, 0, SZ_LINE); + line = fgets (buf, SZ_LINE, fd); + fclose (fd); + unlink (fname); + + return (vot_atoi (line)); + } + return (-1); +} + + +/** + * VOS_GETURLVALUES -- Get the values from a URL request. + */ +static char * +vos_getURLValues (char *fname) +{ + char *ptr, *out, *ip, *op; + FILE *fd; + extern int vos_fileRead(); + + + if (fname && (fd = fopen (fname, "r"))) { + struct stat info; + size_t sz, nr; + + if (stat (fname, &info) < 0) /* read the whole file */ + return (NULL); + sz = info.st_size; + ptr = calloc (sz + 1, sizeof(char)); + out = calloc (sz + 1, sizeof(char)); + nr = vos_fileRead (fileno(fd), ptr, sz); + + /* Check for a service outage. + */ + if (strstr (ptr, "uWSGI Error")) { + if (ptr) free (ptr); + if (out) free (out); + return ( strdup ("SDSS Service not available\n") ); + } + + for (ip=ptr, op=out; *ip; ip++) { + if (*ip == '[') + ; + if (*ip == '"') { + ip++; + while (*ip != '"') /* copy token */ + *op++ = *ip++; + *op++ = '\n'; + while (*ip != '"') /* skip to next token */ + ip++; + } + } + + free ((void *) ptr); + fclose (fd); + unlink (fname); + + return (out); + } + + return (NULL); +} + + +/** + * VOS_SAMPINIT -- Initialize the SAMP interface connection. + */ +static int +vos_sampInit (void) +{ + int sampH = 0; + + + /* If there's no Hub running, don't bother .... + */ + if (!samp_hubRunning()) + return (0); + + /* Initialize the SAMP interface. + */ + sampH = sampInit ("vosloanspec", "VOClient SDSS Spectrum Task"); + if (samp_hubActive (sampH) == 0) + return (0); + + /* Force 'asynch' messaging. + */ + samp_setSyncMode (sampH); + + /* Load metadata. + */ + samp_Metadata (sampH, "author.name", "Mike Fitzpatrick, NOAO"); + samp_Metadata (sampH, "author.email", "fitz@noao.edu"); + samp_Metadata (sampH, "samp.description.html", + "http://iraf.noao.edu/voclient/vosamp.html"); + samp_Metadata (sampH, "samp.icon.url", + "http://iraf.noao.edu/voclient/vao_icon.gif"); + + /* Register with the Hub and begin messaging. + */ + sampStartup (sampH); + + + return (sampH); +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "vosloanspec [<opts>] <obj> | {<ra> <dec>} | {<ra> <dec> <radius>}\n\n" + " where\n" + " -%%,--test Run unit tests\n" + " -h,--help This message\n" + " -v,--verbose Verbose Flag\n" + " -d,--debug Debug Flag\n" + " -r,--return=<obj> Return object\n" + "\n" + " -P,--pos=<ra>,<dec> Set query position (dec degrees)\n" + " -R,--release=<rel> Data release (dr8/dr9/def=current)\n" + " -s,--size=<radius> Set query radius (dec degrees)\n" + " -t,--type=<type> Object type (all|galaxy|qso|star)\n" + " -z,--redshift=<zrange> Select by redshift range string(s)\n" + "\n" + " -c,--count Return only count of results\n" + " -m,--meta Print result position metadata\n" + " -D,--delete Delete spectra after printing metadata\n" + " -l,--limit=<N> Limit to top <N> results\n" + " -u,--urls Get urls to spectra\n" + "\n" + " -S,--samp Broadcase urls to SAMP (as spectrum)\n" + " -T,--table Broadcase urls as VOTable message\n" + " -N,--num=<N> Number of download threads\n" + "\n" + " -f,--file=<file> Input file\n" + " -b,--base=<file> Base filename\n" + " -O,--output=<file> Output file\n" + " -o,--object=<obj> Object name\n" + "\n\n" + " Examples:\n\n" + " 1) Download all galaxy spectra w/in 0.1 deg of the Hubble UDF\n\n" + " %% vosloanspec -s 0.1 -t galaxy HUDF\n" + " %% vosloanspec --size=0.1 --type=galaxy HUDF\n" + "\n" + " 2) Get only the positions of the SDSS spectra around a point\n\n" + " %% vosloanspec -m -d m51\n" + " %% vosloanspec --meta --delete m51\n" + "\n" + " 3) Broadcast 5 spectra around 3c273 to SAMP-enabled apps\n\n" + " %% vosloanspec -l 5 --samp 3c273\t# as a spectrum msg\n" + " %% vosloanspec -l 5 --samp --table 3c273\t# as a table msg\n" + "\n" + " 4) Get all QSO spectra with a redshift > 0.3 (Note an upper range\n" + " must be specified for the redshift range for a valid query)\n\n" + " %% vosloanspec --redshift=0.3-1.0\n" + "\n\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + vo_taskTest (task, "--help", NULL); + + vo_taskTest (task, "-s", "0.1", "-t", "galaxy", "HUDF", NULL); // Ex 1a + vo_taskTest (task, "--size=0.1", "--type=galaxy", "HUDF", NULL); // Ex 1b + vo_taskTest (task, "-m", "-D", "m51", NULL); // Ex 2a + vo_taskTest (task, "--meta", "--delete", "m51", NULL); // Ex 2b + vo_taskTest (task, "-l", "5", "--samp", "3c273", NULL); // Ex 3a + vo_taskTest (task, "-l", "5", "--samp", "--table", "3c273", NULL); // Ex 3b + vo_taskTest (task, "--redshift=0.3-1.0", NULL); // Ex 4 + + vo_taskTestReport (self); +} diff --git a/vendor/voclient/voapps/vospectra.c b/vendor/voclient/voapps/vospectra.c new file mode 100644 index 00000000..ad12f28c --- /dev/null +++ b/vendor/voclient/voapps/vospectra.c @@ -0,0 +1,130 @@ +/** + * VOSPECTRA -- Query all VO Spectra services + * + * Usage: + * vospectra [<opts>] [ <object> | <ra> <dec> ] [ <size> ] + * + * @file vospectra.c + * @author Mike Fitzpatrick + * @date 2/03/13 + * + * @brief Query all VO Image services. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "votParse.h" /* keep these in order! */ +#include "voApps.h" + + +/* Task specific option declarations. Task options are declared using the + * getopt_long(3) syntax. + */ +int vodata (int argc, char **argv, size_t *len, void **result); +int vospectra (int argc, char **argv, size_t *len, void **result); + +static Task self = { "vospectra", vospectra, 0, 0, 0 }; + +extern void vot_setArg (char **argv, int *argc, char *value); + +static void Usage (void); +static void Tests (char *input); + + +/** + * Application entry point. All VOApps tasks MUST contain this + * method signature. + */ +int +vospectra (int argc, char **argv, size_t *reslen, void **result) +{ + char *pargv[argc+2]; + int i, narg = 0, status = OK; + + + /* Initialize result object whether we return an object or not. + */ + *reslen = 0; + *result = NULL; + + /* Do a quick check of the args so we can provide a task-local + * help and test option. Otherwise, we simply pass thru all the + * args to VODATA for processing. + */ + if (strncmp (argv[1],"-h",2) == 0 || strncmp (argv[1],"--help",6) == 0) { + Usage (); return (OK); + } + if (strncmp (argv[1],"-%",2) == 0 || strncmp (argv[1],"--test",6) == 0) { + Tests (NULL); return (self.nfail); + } + + /* Initialize the new argument vector. + */ + vot_setArg (pargv, &narg, argv[0]); + vot_setArg (pargv, &narg, "-t"); + vot_setArg (pargv, &narg, "spectra"); + for (i=1; i < argc; i++) + vot_setArg (pargv, &narg, argv[i]); + + + /** + * The VODATA task does all the real work, we effectively just set the + * "-t spectra" option to force the service type as a logical naming + * convenience for the user. Note that return parameters are handled + * by vodata as well so there is no processing required here. + */ + status = vodata (narg, pargv, reslen, result); + + + /* Clean up. Rememebr to free whatever pointers were created when + * parsing arguments. + */ + for (i=0; i < (argc + 2); i++) + free ((void *) pargv[i]); + + return (status); +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "vospectra [<opts>] votable.xml\n\n" + " where\n" + " -%%,--test run unit tests\n" + " -h,--help this message\n" + "\n" + " <opts> includes all valid VODATA options\n" + "\n" + " Examples:\n\n" + " 1) Query all services for spectra data of 3c273\n\n" + " %% vospectra any 3c273\n" + "\n" + "\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + + vo_taskTest (task, "--help", NULL); + + vo_taskTest (task, "any", "3c273", NULL); + + vo_taskTestReport (self); +} diff --git a/vendor/voclient/voapps/votcat.c b/vendor/voclient/voapps/votcat.c new file mode 100644 index 00000000..d1661f8f --- /dev/null +++ b/vendor/voclient/voapps/votcat.c @@ -0,0 +1,181 @@ +/** + * VOTCAT -- Concatenate multiple VOTables. + * + * Usage: + * votcat [-n] <votable> <votable> .... + * + * @file votcat.c + * @author Mike Fitzpatrick + * @date 6/03/12 + * + * @brief Concatenate multiple VOTables. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> + +#include "votParse.h" +#include "voApps.h" + + + +#define MAX_FILES 1024 + + +static int nfiles = 0; /* Number of input files */ +static int out = 0; /* Output VOTable handle */ + +static int vot[MAX_FILES]; /* First VOTable handle */ +static int res[MAX_FILES]; /* <RESOURCE> handle */ + +static int do_return = 0; /* return object? */ + +/* Task specific option declarations. + */ +int votcat (int argc, char **argv, size_t *len, void **result); + +static Task self = { "votcat", votcat, 0, 0, 0 }; +static char *opts = "hivo:r%:"; +static struct option long_opts[] = { + { "help", 2, 0, 'h'}, /* required */ + { "test", 1, 0, '%'}, /* required */ + { "indent", 2, 0, 'i'}, /* task option */ + { "output", 1, 0, 'o'}, /* task option */ + { "verbose", 2, 0, 'v'}, /* task option */ + { NULL, 0, 0, 0 } +}; + +static void Usage (void); +static void Tests (char *input); + +extern int vot_atoi (char *v); + + +/** + * Application entry point. + */ +int +votcat (int argc, char **argv, size_t *reslen, void **result) +{ + char **pargv, optval[SZ_FNAME]; + char *oname = (char *) NULL, ch; + char *infile[MAX_FILES]; + int i, verbose = 0, indent = 1, pos = 0; + + + if (argc < 3) { + fprintf (stderr, "Usage: votconcat [-o <out>] <vot1> <vot2> ....\n"); + return (1); + } + + /* Parse the argument list. + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + while ((ch = vo_paramNext (opts,long_opts,argc,pargv,optval,&pos)) != 0) { + if (ch > 0) { + switch (ch) { + case '%': Tests (optval); return (self.nfail); + case 'h': Usage (); return (OK); + case 'i': indent = vot_atoi (optval); break; + case 'o': oname = strdup (optval); break; + case 'v': verbose++; break; + case 'r': do_return = 1; break; + default: + fprintf (stderr, "Invalid option '%s'\n", optval); + return (1); + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + infile[nfiles++] = strdup (optval); + } + } + + /* Sanity checks + */ + if (oname == NULL) oname = strdup ("stdout"); + if (strcmp (oname, "-") == 0) { free (oname), oname = strdup ("stdout"); } + + + /* Open output table. + */ + out = vot_openVOTABLE (NULL); + + /* Loop over the input tables on the cmdline. + */ + for (i=0; i < nfiles; i++) { + vot[i] = vot_openVOTABLE (infile[i]); /* Parse the table */ + + /* Concatenate the tables. + */ + if ((res[i] = vot_getRESOURCE (vot[i]))) + vot_attachNode (out, res[i]); + } + + /* Write it out. + */ + vot_writeVOTable (out, oname, indent); + + for (i=0; i < nfiles; i++) + vot_closeVOTABLE (vot[i]); /* close the input tables */ + vot_closeVOTABLE (vot[i]); /* close the output table */ + + + /* Close (and free) the output table and allocated pointers. + */ + if (oname) + free (oname); + for (i=0; i < nfiles; i++) { + if (infile[i]) + free (infile[i]); + } + + vo_paramFree (argc, pargv); + return (OK); +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "generic [<opts>] votable.xml\n\n" + " where\n" + " -%%,--test run unit tests\n" + " -h,--help this message\n" + " -n,--number number output\n" + " -o,--output=<file> output file\n" + " -r,--return return result from method\n" + "\n" + " Examples:\n\n" + " 1) First example\n\n" + " %% votcat test.xml\n" + "\n" + " 2) Second example\n\n" + " %% votcat -o pos.txt test.xml\n" + "\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + + /* First argument must always be the 'self' variable, the last must + * always be a NULL to terminate the cmd args. + */ + vo_taskTest (task, "--help", NULL); +} diff --git a/vendor/voclient/voapps/votcnv.c b/vendor/voclient/voapps/votcnv.c new file mode 100644 index 00000000..7ba0421d --- /dev/null +++ b/vendor/voclient/voapps/votcnv.c @@ -0,0 +1,259 @@ +/** + * VOTCNV -- Convert a VOTable to a different format. + * + * Usage: + * votcnv [<opts>] <votable> + * + * Where + * -f,--fmt <fmt> Output format (XML, CSV, TSV, HTML, etc) + * -h,--help Print help summary + * -i,--indent <N> Indention at each level for VOTable output + * -o,--output <fname> Name of output file + * + * -n,--noheader Don't write a header + * -r,--return Return result to API + * + * <votable> Name of input file to compress + * + * @file votcnv.c + * @author Mike Fitzpatrick + * @date 6/03/12 + * + * @brief Convert a VOTable to a different format. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include "votParse.h" +#include "voApps.h" + + +static char *fmt = NULL; /* format string */ +static int vot = 0; /* VOTable root handle */ +static int indent = 0; /* indention at each level */ +static int hdr = 1; /* print header ?? */ +static int do_return = 0; /* return result from method? */ + +/* Task specific option declarations. + */ +int votcnv (int argc, char **argv, size_t *len, void **result); + +static Task self = { "votcnv", votcnv, 0, 0, 0 }; +static char *opts = "%:f:hi:no:r"; +static struct option long_opts[] = { + { "test", 1, 0, '%'}, /* --test is std */ + { "help", 2, 0, 'h'}, /* --help is std */ + { "fmt", 1, 0, 'f'}, /* output format */ + { "indent", 1, 0, 'i'}, /* XML indention level */ + { "noheader", 2, 0, 'n'}, /* suppress header */ + { "output", 1, 0, 'o'}, /* output name */ + { "return", 2, 0, 'r'}, /* return result to API */ + { NULL, 0, 0, 0 } +}; + + +static void Usage (void); +static void Tests (char *input); + +extern int strdic (char *in_str, char *out_str, int maxchars, char *dict); +extern int vot_isValidFormat (char *fmt); +extern int vot_atoi (char *v); + + + +/** + * VOApps task entry point. + */ +int +votcnv (int argc, char **argv, size_t *reslen, void **result) +{ + int status = OK, pos = 0; + char *iname = NULL, *name = NULL, *oname = NULL, format[SZ_FORMAT]; + char **pargv, ch, optval[SZ_FNAME]; + + + /* Parse the argument list. + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + while ((ch = vo_paramNext (opts,long_opts,argc,pargv,optval,&pos)) != 0) { + if (ch > 0) { + switch (ch) { + case '%': Tests (optval); return (self.nfail); + case 'h': Usage(); return (OK); + case 'f': if (!vot_isValidFormat ((fmt = strdup (optval)))) { + fprintf (stderr, "Error: invalid format '%s'\n", + fmt); + return (ERR); + } + break; + case 'i': indent = vot_atoi (optval); break; + case 'n': hdr--; break; + case 'o': oname = strdup (optval); break; + case 'r': do_return++; break; + default: + fprintf (stderr, "Invalid argument '%s'\n", optval); + return (ERR); + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + iname = strdup (optval); + break; + } + } + + + /* Sanity checks. + */ + if (iname == NULL) iname = strdup ("stdin"); + if (oname == NULL) oname = strdup ("stdout"); + if (strcmp (iname, "-") == 0) { free (iname), iname = strdup ("stdin"); } + if (strcmp (oname, "-") == 0) { free (oname), oname = strdup ("stdout"); } + + fmt = (fmt ? fmt : strdup ("xml")); + + if (do_return) { /* return result */ + if (name) free (name); + oname = calloc (1, SZ_FNAME); + sprintf (oname, "/tmp/votcnv.%d", (int) getpid()); + } else + oname = (oname ? oname : strdup ("stdout")); + + + /* Open and parse the input table. + */ + if ( (vot = vot_openVOTABLE (iname) ) <= 0) { + fprintf (stderr, "Error opening VOTable '%s'\n", iname); + return (ERR); + } + + /* Output the new format. + */ + switch (strdic (fmt, format, SZ_FORMAT, FORMATS)) { + case VOT: vot_writeVOTable (vot, oname, indent); break; + case ASV: vot_writeASV (vot, oname, hdr); break; + case BSV: vot_writeBSV (vot, oname, hdr); break; + case CSV: vot_writeCSV (vot, oname, hdr); break; + case TSV: vot_writeTSV (vot, oname, hdr); break; + case HTML: vot_writeHTML (vot, iname, oname); break; + case SHTML: vot_writeSHTML (vot, iname, oname); break; + case FITS: vot_writeFITS (vot, oname); break; + case XML: vot_writeVOTable (vot, oname, indent); break; + case ASCII: vot_writeASV (vot, oname, hdr); break; + case RAW: vot_writeVOTable (vot, oname, indent); break; + default: + fprintf (stderr, "Unknown output format '%s'\n", fmt); + status = ERR; + } + vot_closeVOTABLE (vot); /* close the table */ + + + /* If we requested a return object, get it from the output file. + */ + if (do_return) { + vo_setResultFromFile (oname, reslen, result); + unlink (oname); + } + + /* Clean up. + */ + if (fmt) free (fmt); + if (name) free (name); + if (iname) free (iname); + if (oname) free (oname); + vo_paramFree (argc, pargv); + + return (status); +} + + +/** + * USAGE -- Print a task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "votcnv [-f <fmt>] [-h] [-i <N>] [-o <outname>] [-n] votable.xml\n\n" + " where\n" + " -f,--fmt <fmt> output format\n" + " -h,--help this message\n" + " -i,--indent <N> indented xml output?\n" + " -n,--noheader disable output header\n" + " -o,--output <name> output filename\n" + " -r,--return return result from method\n" + "\n" + " <fmt> is one of\n" + " vot A new VOTable\n" + " asv ascii separated values\n" + " bsv bar separated values\n" + " csv comma separated values\n" + " tsv tab separated values\n" + " html standalone HTML document\n" + " shtml single HTML <table>\n" + " fits FITS binary table\n" + " ascii ASV alias\n" + " xml VOTable alias\n" + " raw VOTable alias\n" + "\n" + " Examples:\n\n" + " 1) Convert a VOTable to a CSV file:\n\n" + " %% votcnv --fmt=csv test.xml\n" + "\n" + " 2) Rewrite a VOTable with readable indention:\n\n" + " %% votcnv -f vot -i 2 test.xml\n" + "\n" + " 3) Remove indention from a VOTable:\n\n" + " %% votcnv -f vot -i 0 test.xml\n" + ); +} + + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + + /* First argument must always be the 'self' variable, the last must + * always be a NULL to terminate the cmd args. + */ + vo_taskTest (task, "--help", NULL); + + if (access (input, F_OK) != 0) { + fprintf (stderr, "Warning: cannot open file '%s'\n", input); + return; + } + + /* Test each of the conversion formats. + */ + vo_taskTest (task, "--fmt=vot", input, NULL); // Ex 1 + vo_taskTest (task, "--fmt=asv", input, NULL); + vo_taskTest (task, "--fmt=bsv", input, NULL); + vo_taskTest (task, "--fmt=csv", input, NULL); + vo_taskTest (task, "--fmt=tsv", input, NULL); + vo_taskTest (task, "--fmt=html", input, NULL); + vo_taskTest (task, "--fmt=shtml", input, NULL); + vo_taskTest (task, "--fmt=fits", "-o", "test.fits", input, NULL); + vo_taskTest (task, "--fmt=ascii", input, NULL); + vo_taskTest (task, "--fmt=xml", input, NULL); + + vo_taskTest (task, "-f", "vot", "-i", "2", input, NULL); // Ex 2 + vo_taskTest (task, "-f", "vot", "-i", "0", input, NULL); // Ex 3 + vo_taskTest (task, "-f", "csv", "-n", input, NULL); // Ex 4 + + + if (access ("test.fits", F_OK) == 0) unlink ("test.fits"); + + vo_taskTestReport (self); +} + diff --git a/vendor/voclient/voapps/votget.c b/vendor/voclient/voapps/votget.c new file mode 100644 index 00000000..87bef50c --- /dev/null +++ b/vendor/voclient/voapps/votget.c @@ -0,0 +1,1089 @@ +/** + * VOTGET -- Download select/all access references in a VOTable. + * + * Usage: + * + * votget [<opts>] <votable.xml> + * votget [<opts>] --samp # to listen for SMAP messages + * + * Where + * -b,--base <base> Base output filename + * -e,--extn [<extn>] Extension to add to filename (or auto) + * -f,--fmt <fmt> Download only specified <type> + * -s,--sum Use checksum as file number + * -t,--tmp Input file is temporary, delete when done + * -u,--ucd <ucd> Use ucd to identify acref column + * + * -o,--output <fname> Output filename (single download) + * -v,--verbose Verbose output + * -x,--extract Extract access references + * + * -A,--acref <colnum> Col number for acref column (0-indexed) + * -B,--bkg Background, i.e. run in forked child process + * -C,--cache Cache the downloaded file + * -D,--download Set download directory + * -F,--fmtcol <colnum> Col number for format column (0-indexed) + * -N,--num <N> Number of simultaneous downloads + * -S,--samp start as SAMP listener + * -m,--mtype <mtype> mtype to wait for + * + * -h,--help Print help summary + * -d,--debug Debug output + * --test Run unit tests + * + * <votable> VOTable to process + * + * @file votget.c + * @author Mike Fitzpatrick + * @date 6/03/12 + * + * @brief Download select/all access references in a VOTable. + */ + + +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/errno.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <pthread.h> + +#include <curl/curl.h> +#include <curl/types.h> +#include <curl/easy.h> + +#include "samp.h" +#include "votParse.h" +#include "voApps.h" + + +#define MIN_THREADS 4 /* min no. simultaneous thread */ +#define MAX_THREADS 64 /* max no. simultaneous threads */ +#define MAX_DOWNLOADS 4096 /* max no. files to download */ +#define MAX_TRYS 3 /* max download attempts */ + +#define NAXIS_UCD "VOX:Image_Naxis" +#define NAXES_UCD "VOX:Image_Naxes" +#define SCALE_UCD "VOX:Image_Scale" +#define ACREF_UCD "VOX:Image_AccessReference" +#define FORMAT_UCD "VOX:Image_Format" + + +static int vot = 0; /* VOTable handle */ +static int verbose = 0; /* verbose parameter */ +static int debug = 0; /* debug flag */ +static int extract = 0; /* extract references only */ +static int detach = 0; /* run as detached process */ +static int nfiles = 0; /* number of download files */ +static int ngot = 0; /* number of files downloaded */ +static int seq = 1; /* use sequential file numbers */ +static int isCache = 0; /* is this a cache file? */ +static int isTemp = 0; /* is this a temp file? */ +static int force = 0; /* overwrite existing file */ +static int acol = -1; /* access reference column */ +static int tcol = -1; /* image type column */ +static int filenum = 0; /* running download file number */ + +static int nthreads = MIN_THREADS; /* number of download threads */ +static int maxTrys = MAX_TRYS; /* download attempts */ + +static char *base = NULL; /* output base filename */ +static char *extn = NULL; /* output filename extension */ +static char *dir = NULL; /* download directory */ +static char *afname = NULL; /* output acref filename */ + +static char *acref = NULL; /* acref url */ +static char *acref_ucd = NULL; /* acref UCD */ +static char *fmt = NULL; /* image format */ +static char *fmt_ucd = NULL; /* image format UCD */ + +static FILE *afd = (FILE *) NULL; /* acref file descriptor */ + +static pthread_mutex_t counter_mut = PTHREAD_MUTEX_INITIALIZER; + +typedef void (*SIGFUNC)(); /* signal handler type */ + +typedef struct { + char url[SZ_URL]; /* access URL */ + char fname[SZ_URL]; /* local filename */ + int tnum; /* worker thread number */ +} Acref, *AcrefP; + +Acref aclist[MAX_DOWNLOADS]; /* access list */ + + +/* Task specific option declarations. + */ +int votget (int argc, char **argv, size_t *len, void **result); + +static Task self = { "votget", votget, 0, 0, 0 }; +static char *opts = "%:hb:e:f:dstu:o:vxA:BCD:F:N:Sm:"; +static struct option long_opts[] = { + { "base", 1, 0, 'b'}, /* task option */ + { "extn", 1, 0, 'e'}, /* task option */ + { "fmt", 1, 0, 'f'}, /* task option */ + { "sum", 2, 0, 's'}, /* task option */ + { "tmp", 2, 0, 't'}, /* task option */ + { "ucd", 1, 0, 'u'}, /* task option */ + { "output", 1, 0, 'o'}, /* task option */ + { "verbose", 2, 0, 'v'}, /* task option */ + { "extract", 2, 0, 'x'}, /* task option */ + { "acref", 1, 0, 'A'}, /* task option */ + { "bkg", 2, 0, 'B'}, /* task option */ + { "cache", 2, 0, 'C'}, /* task option */ + { "download", 1, 0, 'D'}, /* task option */ + { "fmtcol", 1, 0, 'F'}, /* task option */ + { "num", 1, 0, 'N'}, /* task option */ + { "force", 2, 0, 'O'}, /* task option */ + { "samp", 2, 0, 'S'}, /* task option */ + { "mtype", 1, 0, 'm'}, /* task option */ + + { "help", 2, 0, 'h'}, /* required */ + { "debug", 2, 0, 'd'}, /* required */ + { "test", 1, 0, '%'}, /* required */ + { NULL, 0, 0, 0 } +}; + +static int do_return = 0; /* NOT USED */ +static int do_samp = 0; /* samp listener? */ +static char *mtype = NULL; /* samp mtype */ + + +static void Usage (void); +static void Tests (char *input); + + +/* Public methods. + */ +extern int vot_isValidFormat (char *fmt); +extern int vot_atoi (char *val); +extern int vot_sum32 (char *str); +extern char *strcasestr (); + + +/* Private methods. + */ +static void votableHandler (char *url, char *tblId, char *name); + +static int vot_procFile (char *iname); +static int vot_isVOTable (char *infile); +static int vot_acrefColumn (handle_t tab); +static int vot_typeColumn (handle_t tab); +static int vot_loadText (char *infile); +static int vot_loadVOTable (char *infile); +static int vot_getData (char *url, char *ofname); + +static void vot_saveAcref (char *acref, int num, int fnum); +static void *vot_getAclist (void *arg); +static void vot_printAclist (); +static void vot_reaper (int sig, int *arg1, int *arg2); + + + + +/** + * Program entry point. + */ +int +votget (int argc, char **argv, size_t *reslen, void **result) +{ + char **pargv, optval[SZ_FNAME]; + char *iname = NULL, ch; + int samp = 0, pos = 0, stat = OK; + + + /* Initialize. + */ + *reslen = 0; + *result = NULL; + + + /* Parse the argument list. + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + while ((ch = vo_paramNext (opts,long_opts,argc,pargv,optval,&pos)) != 0) { + if (ch > 0) { + + switch (ch) { + case '%': Tests (optval); return (self.nfail); + case 'h': Usage (); return (OK); + + case 'b': base = strdup (optval); break; + case 'e': extn = strdup (optval); break; + case 'f': if (!vot_isValidFormat ((fmt = strdup (optval)))) { + fprintf (stderr, "Error: invalid format '%s'\n", + fmt); + return (ERR); + } + break; + case 'd': debug++; break; + case 's': seq=0; break; + case 't': isTemp++; break; + case 'u': acref_ucd = strdup (optval); break; + + case 'o': afname = strdup (optval); break; + case 'v': verbose++; break; + case 'x': extract++; break; + + case 'A': acol = vot_atoi (optval); break; + case 'B': detach++; break; + case 'C': isCache++; break; + case 'D': dir = strdup (optval); break; + case 'F': tcol = vot_atoi (optval); break; + case 'N': nthreads = vot_atoi (optval); break; + case 'O': force++; break; + case 'S': do_samp++; break; + case 'm': mtype = strdup (optval);; break; + + default: + fprintf (stderr, "Invalid option '%c'\n", ch); + return (1); + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + iname = strdup (optval); + } + } + + + /* Sanity checks + */ + if (iname == NULL) iname = strdup ("stdin"); + if (strcmp (iname, "-") == 0) { free (iname), iname = strdup ("stdin"); } + + + /* Setup defaults and initialize. + */ + do_return = 0; + memset (&aclist[0], 0, (sizeof (Acref) * MAX_DOWNLOADS)); + + if (afname && (afd = fopen (afname, "a+")) == (FILE *) NULL) { + if (verbose) + fprintf (stderr, "Error: cannot open aclist file '%s'\n", afname); + return (ERR); + } + + if (!base) base = strdup ("file"); + if (!mtype) mtype = strdup ("table.load.votable"); + if (!fmt_ucd) fmt_ucd = strdup (FORMAT_UCD); + if (!acref_ucd) acref_ucd = strdup (ACREF_UCD); + + + if (do_samp) { + /* Initialize and startup the SAMP interface. Wait for a message. + */ + if (verbose) + fprintf (stderr, "Initializing samp ....\n"); + samp = sampInit ("votget", "VOClient Task"); + samp_Subscribe (samp, mtype, votableHandler); + if (sampStartup (samp) < 0) + return (ERR); + + if (verbose) + fprintf (stderr, "Type <cr> to quit ...."); + while (fgetc(stdin) != EOF) + break; + + sampShutdown (samp); + + } else { + /* Process the file. + */ + stat = vot_procFile (iname); + } + + + /* Close the table and clean up. + */ + if (base) free (base); + if (extn) free (extn); + if (dir) free (dir); + if (afname) free (afname); + if (acref) free (acref); + if (acref_ucd) free (acref_ucd); + if (fmt) free (fmt); + if (fmt_ucd) free (fmt_ucd); + if (mtype) free (mtype); + + vo_paramFree (argc, pargv); + if (detach) + exit (OK); + else + return (stat); +} + + +/** + * VOTABLEHANDLER -- Callback for the load.table.votable message. + */ +static void +votableHandler (char *url, char *tblId, char *name) +{ + char fname[SZ_FNAME]; + + + memset (fname, 0, SZ_FNAME); + + if (verbose) + printf ("\n"); + + + if (strncmp (url, "http://", 7) == 0) { + strcpy (fname, "/tmp/votgetXXXXXX"); /* temp download name */ + mktemp (fname); + if (vot_getData (url, fname) < 0) + fprintf (stderr, "Error accessing url '%s'\n", url); + + vot_procFile (fname); + unlink (fname); + + } else if (strncmp (url, "file://", 7) == 0) { + strcpy (fname, &url[7]); + vot_procFile (fname); + + } else { + fprintf (stderr, "Error: unsupported URL type '%s'\n", url); + return; + } + + /* Clean up for the next file to process. + */ + memset (&aclist[0], 0, (sizeof (Acref) * MAX_DOWNLOADS)); + nfiles = 0; +} + + +/** + * VOT_PROCFILE -- Process a VOTable file. + */ +static int +vot_procFile (char *iname) +{ + int stat = OK; + + + /* Determine the type of input file. + */ + if (strncmp (iname, "http://", 7) == 0) { + if (vot_loadVOTable (iname) < 0) { + fprintf (stderr, "Error opening votable '%s'\n", iname); + return ( (stat = ERR) ); + } + + } else { + switch ((vot = vot_isVOTable (iname))) { + case -1: fprintf (stderr, "Error opening file '%s'\n", iname); + return ( (stat = ERR) ); + case 0: if (vot_loadText (iname) < 0) { + fprintf (stderr, "Error opening text file '%s'\n", iname); + return ( (stat = ERR) ); + } + break; + case 1: if (vot_loadVOTable (iname) < 0) { + fprintf (stderr, "Error opening votable '%s'\n", iname); + return ( (stat = ERR) ); + } + break; + } + } + + + /* If all we're doing is extracting the URLs we can quit now. + */ + if (extract) + return (OK); + + if (debug) { + fprintf (stderr, "acol = %d tcol = %d\n", acol, tcol); + fprintf (stderr, "Downloading %d files ....\n", nfiles); + vot_printAclist (); + } + + + /* If we've been asked to detach, fork off to do the downloads in + * a child, and return to the caller. + */ + if (detach) { + pid_t pid; + + signal (SIGCHLD, (SIGFUNC)vot_reaper); + switch ((pid = fork ())) { + case -1: return (ERR); /* We are an error */ + case 0: break; /* We are the child */ + default: return (OK); /* We are the parent */ + } + } + + + /* Initialize the download directory. + */ + if (dir) { + if (access (dir, F_OK) < 0) + mkdir (dir, 0755); + if (access (dir, W_OK) < 0) { + if (verbose) + fprintf (stderr, "Error: Cannot write to directory '%s'\n", dir); + return (ERR); + } + chdir (dir); + } + + /* Do the downloads. + */ + if (nfiles < MIN_THREADS) + nthreads = nfiles; + + if (nthreads == 1) { + vot_getAclist (NULL); + + } else { + /* Spawn the worker threads. + */ + int rc = 0, tc = 0, status = 0, tnum[MAX_THREADS]; + pthread_attr_t attr; /* thread attributes */ + pthread_t thread[MAX_THREADS]; + + + /* Initialize the service processing thread attributes and run 'em. + */ + pthread_attr_init (&attr); + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE); + + if (verbose) + fprintf (stderr, "Starting download ....\r"); + + for (tc=0; tc < nthreads; tc++) { + tnum[tc] = tc; + if ((rc = pthread_create (&thread[tc], &attr, vot_getAclist, + (void *)&tnum[tc]))) { + fprintf (stderr, "ERROR: pthread_create() fails, code=%d\n", + rc); + return (-1); + } + } + + /* Free attribute and wait for the threads to complete. + */ + pthread_attr_destroy (&attr); + for (tc=0; tc < nthreads; tc++) { + if ((rc = pthread_join (thread[tc], (void **)&status)) ) { + if (rc != ESRCH) { + fprintf (stderr, + "ERROR: pthread_join() fails, code=%d status=%d\n", + rc, status); + return (-1); + } + } + } + + if (verbose) { + fprintf (stderr, + "Downloaded %d files -- Download complete (Total: %d)\n", + nfiles, (filenum+1)); + fflush (stderr); + } + } + + + /* Remove input file if it is temporary. + */ + if (isTemp) + unlink (iname); + + return (stat); +} + + + + +/** + * VOT_USAGE -- Print the task usage and exit. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "votget [<opts>] [ <votable.xml> | <urls.txt> ]\n\t" + "votget [<opts>] --samp # to listen for SMAP messages\n" + "\n" + "Where\n" + " -b,--base <base> Base output filename\n" + " -e,--extn [<extn>] Extension to add to filename (or auto)\n" + " -f,--fmt <fmt> Download only specified <type>\n" + " -s,--sum Use 32-bit checksum as file numbers\n" + " -t,--tmp Input file is temporary, delete when done\n" + " -u,--ucd <ucd> Use ucd to identify acref column\n" + "\n" + " -o,--output <fname> Output filename (single download)\n" + " -v,--verbose Verbose output\n" + " -x,--extract Extract access references\n" + "\n" + " -A,--acref <colnum> Col number for acref column (0-indexed)\n" + " -B,--bkg Background, i.e. run in forked child\n" + " -C,--cache Cache the downloaded file\n" + " -D,--download Set download directory\n" + " -F,--fmtcol <colnum> Col number for format column (0-indexed)\n" + " -N,--num <N> Number of simultaneous downloads\n" + " -S,--samp start as SAMP listener\n" + "\n" + " -h,--help Print help summary\n" + " -d,--debug Debug output\n" + " --test Run unit tests\n" + "\n" + " <votable> VOTable to process\n" + "\n" + " Examples:\n\n" + + " 1) Download all files in the VOTable 'results.xml', 3 files at\n" + " a time:\n\n" + " %% votget -N 3 results.xml\n" + "\n" + " 2) Start as a SAMP listener waiting for VOTable events to be \n" + " broadcast, saved files will begin with the string 'foo' and \n" + " contain a 'fits' filename extension:\n\n" + " %% votget -b foo -e fits -S\n" + "\n" + " To exit the task, hit the <CR>.\n" + "\n" + " 3) Download all the urls in the file 'urls.txt':\n\n" + " %% votget -b foo urls.txt\n" + "\n" + " 4) Extract all the access references in a VOTable:\n\n" + " %% votget -x results.xml\n" + "\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + char *urls = "http://iraf.noao.edu/votest/sia.xml\n"; + + + vo_taskTest (task, "--help", NULL); + + if (access (input, F_OK) != 0) { + fprintf (stderr, "Warning: cannot open file '%s'\n", input); + return; + } + + vo_taskTestFile (urls, "urls.txt"); + + vo_taskTest (task, "-N", "3", input, NULL); // Ex 1 + vo_taskTest (task, "-b", "foo", input, NULL); // Ex 3 + vo_taskTest (task, "-x", input, NULL); // Ex 4 + vo_taskTest (task, "-x", "-o", "/tmp/acref", input, NULL); + + if (access ("/tmp/acref", F_OK) == 0) unlink ("/tmp/acref"); + if (access ("urls.txt", F_OK) == 0) unlink ("urls.txt"); + + vo_taskTestReport (self); +} + + + +/********************************************************************** +** Private Procedures +**********************************************************************/ + +/** + * VOT_REAPER -- Catch a SIGCHLD signal and reap all children. + */ +static void +vot_reaper ( + int sig, /* signal which was trapped */ + int *arg1, /* not used */ + int *arg2 /* not used */ +) +{ + int status=0, pid=0; + + while ((pid = waitpid ((pid_t) 0, &status, WNOHANG)) > 0) + ; +} + + +/** + * VOT_LOADTEXT -- Load the access list from a text file. We assume the + * list is simply one url per line. + */ +static int +vot_loadText (char *infile) +{ + int i = 0, fd, nread = 0, tnum = 0, sz = 0; + char *acref, *buf, *ip; + struct stat info; + + + nfiles = 0; + memset (&aclist[0], 0, (sizeof (Acref) * MAX_DOWNLOADS)); + + if ((fd = open (infile, O_RDONLY)) < 0) + return (-1); + + if (stat (infile, &info) < 0) /* read the whole file */ + return (-1); + sz = info.st_size; + buf = calloc (sz + 1, sizeof(char)); + nread = read (fd, buf, sz); + close (fd); + + acref = buf; /* point to 1st url */ + for (i=0; *acref; i++) { + for (ip=acref; *ip && *ip != '\n'; ip++) + ; + *ip = '\0'; + + vot_saveAcref (acref, i, filenum++); + + acref = ip + 1; + nfiles++; + tnum++; + } + + if (afd) /* close the acref file */ + fclose (afd); + + return (nfiles); +} + + +/** + * VOT_LOADVOTABLE -- Load the access list from a VOTable. + */ +static int +vot_loadVOTable (char *infile) +{ + int i, tnum = 0; + int res, tab, data, tdata, tr; + char *acref; + + + nfiles = 0; + memset (&aclist[0], 0, (sizeof (Acref) * MAX_DOWNLOADS)); + + /* Open the table. This also parses it. + */ + if ( (vot = vot_openVOTABLE (infile) ) <= 0) { + if (verbose) + fprintf (stderr, "Error opening VOTable '%s'\n", infile); + return (ERR); + } + + /* Loop over all the resources in the file. In most cases there will + * only be one <RESOURCE>, if not then the selection applies to all + * valid tables. + */ + for (res = vot_getRESOURCE (vot); res; res = vot_getNext (res)) { + + /* Get the <TABLE> element. + */ + if (! (tab = vot_getTABLE (res))) { + if (verbose) fprintf (stderr, "Error: No <TABLE> in <RESOURCE>\n"); + continue; + } + if ((data = vot_getDATA (tab))) + tdata = vot_getTABLEDATA (data); + else + continue; /* empty data table */ + + /* Loop through the FIELDs to find the acref. Let the cmdline param + * override the acref column ucd. + */ + acol = (acol < 0 ? vot_acrefColumn (tab) : acol); + tcol = (tcol < 0 ? vot_typeColumn (tab) : tcol); + + /* Now scan the data table for acrefs. We got the acref column above + * so lookup the table cell directly for each row, either printing + * out the acref for a simple extract, or by adding to the access + * list to be processed below. + */ + i = 0; + for (tr=vot_getTR (tdata); tr; tr=vot_getNext(tr)) { + acref = vot_getTableCell (tdata, i, acol); + if (tcol >= 0) { + char *format = vot_getTableCell (tdata, i, tcol); + + if (format && fmt && strcasestr (format, fmt) == NULL) + continue; + } + + vot_saveAcref (acref, i, filenum++); + + nfiles++; + tnum++; + i++; + } + } + + + /* Clean up. + */ + if (afd) /* close the acref file */ + fclose (afd); + + vot_closeVOTABLE (vot); + + return (nfiles); +} + + +/** + * VOT_SAVEACREF -- Save the URL to the access list. + */ +static void +vot_saveAcref (char *acref, int num, int fnum) +{ + if (afd) + fprintf (afd, "%s\n", acref); + else if (extract) + fprintf (stderr, "%s\n", acref); + else { + /* Save to the access list. + */ + aclist[num].tnum = ((nthreads == 1) ? 0 : (num % nthreads)); + strcpy (aclist[num].url, acref); + if (seq) + sprintf (aclist[num].fname, "%s%04d", base, (int) fnum); + else + sprintf (aclist[num].fname, "%s%d", base, vot_sum32 (acref)); + } +} + + +/** + * VOT_ISVOTABLE -- Determine in the input file is a VOTable or URL @file. + * We return zero if the file cannot be parsed as a valid VOTable (i.e. + * we assume it is an @file of URLs), or else we return the root handle to + * the parsed file. + */ + +#define SZ_READ 2880 + +static int +vot_isVOTable (char *infile) +{ + FILE *fd = (FILE *) NULL; + char buf[SZ_READ], fname[SZ_READ]; + register int nread;; + + + memset (fname, 0, SZ_READ); + if (strncmp (infile, "file://", 7) == 0) + strcpy (fname, &infile[7]); + else + strcpy (fname, infile); + + /* read the first 1024 bytes and search for a 'votable' string... */ + if (access (fname, F_OK) < 0) { + if (verbose) + fprintf (stderr, "Error: Cannot open input file '%s'\n", fname); + return (-1); + + } else if ((fd = fopen (fname, "r"))) { + memset (buf, 0, SZ_READ); + nread = fread (buf, sizeof (char), SZ_READ, fd); + fclose (fd); + + return (strcasestr (buf, "votable") ? 1 : 0); + } + return ( 0 ); +} + + +/** + * VOT_ACREFCOLUMN -- Determine the access column for the given table. + */ +static int +vot_acrefColumn (handle_t tab) +{ + register int i = 0, acol = -1; + handle_t field; + char *ucd; + + + /* Loop through the FIELDs to find the acref. + */ + for (field=vot_getFIELD(tab); field; field=vot_getNext(field),i++) { + ucd = vot_getAttr (field, "ucd"); + if (ucd && strcasecmp (acref_ucd, ucd) == 0) { + acol = i; + break; + } + } + + if (acol < 0) { /* make sure we found a column */ + if (verbose) + fprintf (stderr, "Error: no acref column found (%s)\n", acref); + return (-1); + } + + return (acol); +} + + +/** + * VOT_TYPECOLUMN -- Determine the type column for the given table. + */ +static int +vot_typeColumn (handle_t tab) +{ + register int i = 0; + handle_t field; + char *ucd; + + + /* Loop through the FIELDs to find the type. Use a generous match. + */ + if (tcol < 0) { + for (field=vot_getFIELD(tab); field; field=vot_getNext(field),i++) { + ucd = vot_getAttr (field, "ucd"); + if (ucd && strcasestr (ucd, fmt_ucd)) { + tcol = i; + break; + } + } + } + + return (tcol); +} + + +/** + * VOT_GETACLIST -- Download all the files for the specified thread. + */ +static void * +vot_getAclist (void *arg) +{ + register int i, j, done = 0, ret = 0; + int threadNum = 0; + + + if (arg) + threadNum = *(int *)arg; + + for (i=0; i < nfiles; i++) { + if (aclist[i].tnum == threadNum) { + for (j=0; j < maxTrys; j++) { + if ((ret = vot_getData (aclist[i].url, aclist[i].fname))) + break; + } + done += ret; + } + } + +/* + pthread_exit (NULL); +*/ + return ((void *) NULL); +} + + +/** + * VOT_GETDATA -- Utility routine to do a simple URL download to the file. + */ +static int +vot_getData (char *url, char *ofname) +{ + int stat = 0; + char lockfile[SZ_FNAME], dot[SZ_FNAME], errBuf[CURL_ERROR_SIZE]; + char fname[SZ_FNAME], ffname[SZ_FNAME]; + FILE *fd; + CURL *curl_handle; + + + /* FIXME */ + if (extn) + sprintf (ffname, "%s.%s", ofname, extn); + else { + sprintf (ffname, "%s.fits", ofname); + } + + if (access (ofname, F_OK) == 0 || access (ffname, F_OK) == 0) { + /* file already exists */ + if (force) + unlink (ofname); + else + return (1); + } + + + /* Initialize the lock file. + */ + memset (lockfile, 0, SZ_FNAME); + memset (dot, 0, SZ_FNAME); + + sprintf (lockfile, ".%s.LOCK", ofname); + sprintf (dot, ".%s", ofname); + + if (access (lockfile, F_OK) == 0 && access (dot, F_OK) < 0) { + /* Download currently in progress, perhaps on another thread? + */ + return (0); + } else if (access (lockfile, F_OK) == 0 && access (dot, F_OK) == 0) { + /* Download complete, stray lockfile. + */ + unlink (lockfile); + } else if (access (lockfile, F_OK) < 0) { + /* No lock file, create one. + */ + creat (lockfile, O_CREAT); + } + + + /* Append filename extension if specified. + */ + if (extn) + sprintf (fname, "%s.%s", ofname, extn); + else + strcpy (fname, ofname); + + + /* For the CURL operation to download the file. + */ + curl_global_init (CURL_GLOBAL_ALL); /* init curl session */ + curl_handle = curl_easy_init (); + + /* Open the output file. + */ + if ((fd = fopen (fname, "wb")) == NULL) { + if (verbose) + fprintf (stderr, "Error: cannot open output file '%s'\n", fname); + curl_easy_cleanup (curl_handle); + return 0; + } + + /* Set cURL options + */ + curl_easy_setopt (curl_handle, CURLOPT_URL, url); + curl_easy_setopt (curl_handle, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt (curl_handle, CURLOPT_WRITEDATA, fd); + curl_easy_setopt (curl_handle, CURLOPT_ERRORBUFFER, errBuf); + curl_easy_setopt (curl_handle, CURLOPT_FOLLOWLOCATION, 1); + + /* Do the download. + */ + if ((stat = curl_easy_perform (curl_handle)) != 0) { + /* Error in download, clean up. + */ + if (verbose) + fprintf (stderr, "Error: can't download '%s' : %s\n", url, errBuf); + unlink (fname); unlink (lockfile); + fclose (fd); /* close the file */ + curl_easy_cleanup (curl_handle); /* cleanup curl stuff */ + return (0); + } + + fflush (fd); + fclose (fd); /* close the file */ + curl_easy_cleanup (curl_handle); /* cleanup curl stuff */ + + /* Save the URL to a "dotfile" is we're downloading to a cache. + */ + if (isCache) { + if ((fd = fopen (dot, "w")) == NULL) { /* open cache file */ + if (verbose) + fprintf (stderr, "Error: cannot open cache file '%s'\n", dot); + return 0; + } + fprintf (fd, "%s\n", url); + fclose (fd); + } + + /* If we didn't specify an extension, try to determin the file type + * automatically. + */ + if (!extn) { + int i = 0, dfd, maxtrys = 30; + + if ((dfd = open (fname, O_RDONLY)) > 0) { + char buf[1024], new[SZ_FNAME]; + unsigned short *s = (unsigned short *) NULL; + + (void) read (dfd, buf, 1024); + + s = (unsigned short *) buf; + memset (new, 0, SZ_FNAME); + if ((s[0] == 35615 && s[1] == 2056) || /* GZIP file */ + (s[0] == 8075 && s[1] == 2048)) { + char gz[SZ_FNAME], cmd[SZ_FNAME]; + + memset (gz, 0, SZ_FNAME); + sprintf (gz, "%s.gz", fname); + memset (cmd, 0, SZ_FNAME); + sprintf (cmd, "gunzip %s", gz); + + rename (fname, gz); /* FIXME !!! */ + system (cmd); + + close (dfd); + if ((dfd = open (fname, O_RDONLY)) > 0) { + (void) lseek (dfd, 0, SEEK_SET); + (void) read (dfd, buf, 1024); + } + } + + memset (new, 0, SZ_FNAME); + if (strncmp ("SIMPLE", buf, 6) == 0) { /* FITS */ + sprintf (new, "%s.fits", fname); + rename (fname, new); + for (i=0; i < maxtrys; i++) { + if (access (new, F_OK) != 0) + sleep (1); + } + } + + close (dfd); + } + } + + pthread_mutex_lock (&counter_mut); + ngot++; + if (verbose) { + fprintf (stderr, "Downloaded %d of %d files ....\r", ngot, nfiles); + fflush (stderr); + } + pthread_mutex_unlock (&counter_mut); + + /* Remove the lock file to indicate we are done. + */ + unlink (lockfile); + + return (1); +} + + + +/****************************************************************************** +** Debug Utilities +******************************************************************************/ + +/** + * VOT_GETACLIST -- Download all the files for the specified thread. + */ +static void +vot_printAclist () +{ + register int i; + + fprintf (stderr, "\nAccess List: nfiles = %d\n", nfiles); + for (i=0; i < nfiles; i++) { + fprintf (stderr, "%2d: url='%20.20s...' fname='%s' tnum=%d\n", + i, aclist[i].url, aclist[i].fname, aclist[i].tnum); + } +} diff --git a/vendor/voclient/voapps/votinfo.c b/vendor/voclient/voapps/votinfo.c new file mode 100644 index 00000000..2a89e703 --- /dev/null +++ b/vendor/voclient/voapps/votinfo.c @@ -0,0 +1,455 @@ +/* + * VOTINFO -- Print information about the structure of a VOTable. + * + * Usage: + * votinfo [-v] [-w] <votable> + * + * @file votinfo.c + * @author Mike Fitzpatrick + * @date 6/03/11 + * + * @brief Print information about the structure of a VOTable. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "voApps.h" +#include "votParse.h" + +#define N_ITEMS "|param|info|rows|cols|resources|" + +#define N_PARAMS 0 /* numberOf values */ +#define N_INFO 1 +#define N_ROWS 2 +#define N_COLS 3 +#define N_RESOURCES 4 + +#define SZ_RESBUF 8192 + + +static int vot = 0; /* VOTable handle */ +static int size = 0; /* print size only */ +static int warn = 0; /* warning options */ +static int numberOf = 0; /* element values */ +static int verbose = 0; /* verbose output */ +static int getCols = 0; /* get column names */ +static int getDesc = 0; /* get <DESCRIPTION> */ +static int getInfo = 0; /* get <INFO> */ +static int getParam = 0; /* get <PARAM> */ +static int getQuery = 0; /* get <INFO> QUERY_STATUS val */ +static int do_return = 0; /* return result? */ + +static char resbuf[SZ_RESBUF]; /* result buffer */ + + +/* Task specific option declarations. + */ +int votinfo (int argc, char **argv, size_t *len, void **result); + +static Task self = { "votinfo", votinfo, 0, 0, 0 }; + +static char *opts = "%:bc::dhin:pqrsvw"; +static struct option long_opts[] = { + { "test", 1, 0, '%'}, + { "help", 2, 0, 'h'}, + { "brief", 2, 0, 'b'}, + { "columns", 2, 0, 'c'}, + { "description", 2, 0, 'd'}, + { "info", 2, 0, 'i'}, + { "numberOf", 1, 0, 'n'}, + { "param", 2, 0, 'p'}, + { "query_status", 2, 0, 'q'}, + { "return", 2, 0, 'r'}, + { "size", 2, 0, 's'}, + { "verbose", 2, 0, 'v'}, + { "warn", 2, 0, 'w'}, + { NULL, 0, 0, 0 } +}; + + +static void Usage (void); +static void Tests (char *input); + +extern void ppMultiLine (char *result, int poffset, int pwidth, int maxchars); +extern int strdic (char *in_str, char *out_str, int maxchars, char *dict); + + + +/** + * Application entry point. + */ +int +votinfo (int argc, char **argv, size_t *reslen, void **result) +{ + char *iname, *id, *name, *ucd, *desc, *value, *numpar = NULL, *clist=NULL; + char **pargv, optval[SZ_FNAME], param[SZ_FNAME]; + int res, tab, data, tdata, field, handle, status = OK; + int i, nlen, ncols, nrows, pos, ch; + + + /* Initialize. + */ + size = 0; + warn = 0; + verbose = 0; + iname = NULL; + memset (param, 0, SZ_FNAME); + memset (optval, 0, SZ_FNAME); + memset (resbuf, 0, SZ_RESBUF); + + *reslen = 0; + *result = NULL; + + + /* Parse the argument list. + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + while ((ch = vo_paramNext (opts,long_opts,argc,pargv,optval,&pos)) != 0) { + if (ch > 0) { + switch (ch) { + case '%': Tests (optval); return (self.nfail); + case 'h': Usage (); return (OK); + + case 'b': verbose=0; break; + case 'c': + if (optval[0]) { + if (optval[0] == 'i') { /* ID */ + clist = "id"; + } else if (optval[0] == 'n') { /* NAME */ + clist = "name"; + } else if (optval[0] == 'u') { /* UCD */ + clist = "ucd"; + } + } + getCols=1; break; + case 'd': getDesc=1; break; + case 'i': getInfo=1; break; + case 'n': numberOf++, numpar = strdup (optval); break; + case 'p': getParam=1; break; + case 'q': getQuery=1; break; + case 'r': do_return=1; break; + case 's': size++; break; + case 'v': verbose++; break; + case 'w': warn++; break; + default: + fprintf (stderr, "Invalid option '%s'\n", optval); + return (1); + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + iname = strdup (optval); + break; + } + } + + + /* Sanity checks + */ + if (iname == NULL) + iname = strdup ("stdin"); + vot_setWarnings (warn); + + /* Open the table. This also parses it. + */ + if ( (vot = vot_openVOTABLE (iname) ) <= 0) { + fprintf (stderr, "Error opening VOTable '%s'\n", iname); + return (1); + } + + res = vot_getRESOURCE (vot); /* get handles */ + tab = vot_getTABLE (res); + if ((data = vot_getDATA (tab))) { + tdata = vot_getTABLEDATA (data); + nrows = vot_getNRows (tdata); + ncols = vot_getNCols (tdata); + } else + tdata = nrows = ncols = 0; + + if (numberOf) { + switch (strdic (numpar, param, SZ_FNAME, N_ITEMS)) { + case N_PARAMS: + if ((handle = vot_getPARAM (res)) > 0) { + if (do_return) + vo_setResultFromInt (vot_getLength(handle), reslen, result); + else + printf ("%d\n", vot_getLength(handle)); + } else + printf ("0\n"); + break; + case N_INFO: + if ((handle = vot_getINFO (res)) > 0) { + if (do_return) + vo_setResultFromInt (vot_getLength(handle), reslen, result); + else + printf ("%d\n", vot_getLength(handle)); + } else + printf ("0\n"); + break; + case N_ROWS: + if (do_return) + vo_setResultFromInt (nrows, reslen, result); + else + printf ("%d\n", nrows); + break; + case N_COLS: + if (do_return) + vo_setResultFromInt (ncols, reslen, result); + else + printf ("%d\n", ncols); + break; + case N_RESOURCES: + if (do_return) + vo_setResultFromInt (vot_getLength (res), reslen, result); + else + printf ("%d\n", vot_getLength (res)); + break; + default: + fprintf (stderr, "Unknown number request '%s'\n", param); + status = ERR; + } + + + } else if (size) { + if (do_return) { + sprintf (resbuf, "%d %d", nrows, ncols); + vo_setResultFromString (resbuf, reslen, result); + } else + printf ("%d %d\n", nrows, ncols); + + + } else if (getCols) { + + printf ("%3s %20.20s\t%20.20s\t%20.20s\n", "Col", + "ID", "Name", "UCD"); + printf ("%3s %20.20s\t%20.20s\t%20.20s\n", "===", "==", "====", "==="); + + for (i=1, field = vot_getFIELD(tab); field; field=vot_getNext (field)) { + id = vot_getAttr (field, "id"); + name = vot_getAttr (field, "name"); + ucd = vot_getAttr (field, "ucd"); + + printf ("%3d %20.20s\t%20.20s\t%20.20s\n", i, + (id ? id : "(none)"), (name ? name : "(none)"), + (ucd ? ucd : "(none)")); + if (verbose) { + if ( (desc = vot_getValue (vot_getDESCRIPTION (field))) ) + printf ("\t Desc: %-s\n", desc); + } + i++; + } + + + } else if (getDesc) { + char *desc = NULL; + + if ((handle = vot_getDESCRIPTION (vot))) + desc = vot_getValue (handle); + else if ((handle = vot_getDESCRIPTION (res))) + desc = vot_getValue (handle); + else + desc = "none"; + if (do_return) + vo_setResultFromString ((desc ? desc : "none"), reslen, result); + else + printf ("%s\n", (desc ? desc : "none")); + + + } else if (getParam || getInfo) { + handle = (getParam ? vot_getPARAM (res) : vot_getINFO (res)); + if (handle > 0) { + char buf[SZ_FNAME]; + + nlen = vot_getLength (handle); + for (nlen-- ; handle; handle = vot_getNext (handle), nlen--) { + name = vot_getAttr (handle, "name"); + value = vot_getAttr (handle, "value"); + memset (buf, 0, SZ_FNAME); + sprintf (buf, "%s = %s\n", name, value); + strcat (resbuf, buf); + } + + if (do_return) + vo_setResultFromString (resbuf, reslen, result); + else + printf ("%s", resbuf); + } + + + } else if (getQuery) { + int found = 0, resval = 0; + + if ((handle = vot_getINFO (res)) > 0) { + nlen = vot_getLength (handle); + for (nlen-- ; handle; handle = vot_getNext (handle), nlen--) { + name = vot_getAttr (handle, "name"); + if (name && strncasecmp (name, "QUERY_STATUS", 12) == 0) { + value = vot_getAttr (handle, "value"); + found++; + break; + } + } + } + + resval = (found ? (strncasecmp (value, "OK", 2) != 0) : -1); + if (do_return) + vo_setResultFromInt (resval, reslen, result); + else + printf ("%d\n", resval); + + + } else { + /* Print a table summary. + */ + printf ("%s\n\n", (iname[0] == '-' ? "stdin" : iname)); + printf (" Resources: %d\tType: %-12s\t" + " Table Size: %d x %d\n", + vot_getLength (res), vot_getDATATypeString (data), ncols, nrows); + + if ((handle = vot_getINFO (res)) > 0) + printf (" INFO: %d\n", vot_getLength (handle)); + + if ((handle = vot_getPARAM (res)) > 0) + printf (" PARAM: %d\t", + (nlen=vot_getLength (handle))); + for (nlen-- ; handle; handle=vot_getNext(handle),nlen--) { + if ((name = vot_getAttr (handle, "id")) == NULL) + if ((name = vot_getAttr (handle, "name")) == NULL) + name = "<noname>"; + value = vot_getAttr (handle, "value"); + printf ("%s = %s ", name, value); + if (nlen) + printf ("\n\t\t\t"); + } + printf ("\n"); + +#ifdef OLD_VOTABLE + if ((handle = vot_getCOOSYS (res))) + printf (" COOSYS: %d\n", vot_getLength (handle)); +#endif + + if ((handle = vot_getDESCRIPTION (res))) { + desc = vot_getValue (handle); + printf (" Description: "); + ppMultiLine (desc, 16, 60, 4096); + printf ("\n"); + } + + + /* Print the column info in verbose mode. + */ + if (verbose) { + printf ("\n\t\t\tName\t\t\tUCD\n"); + i = 0; + for (field=vot_getFIELD(tab); field; field=vot_getNext (field)) { + name = vot_getAttr (field, "name"); + ucd = vot_getAttr (field, "ucd"); + + printf (" Field %2d: %-20s\t%-30s\n", + ++i, (name ? name : ""), (ucd ? ucd : "")); + if (verbose > 1) { + if ( (desc = vot_getValue (vot_getDESCRIPTION (field))) ) + printf ("\t Desc: %-s\n", desc); + } + } + } + } + + if (iname) free (iname); + + vo_paramFree (argc, pargv); + vot_closeVOTABLE (vot); /* close the table */ + + return (status); +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "votinfo [<opts>] votable.xml\n\n" + " where\n" + " -b,--brief brief output\n" + " -d,--description print <DESCRIPTION> elements\n" + " -h,--help this message\n" + " -i,--info print <INFO> elements\n" + " -n,--numberOf=<what> get number of specified elements\n" + " -p,--param print <PARAM> elements\n" + " -q,--query_status print QUERY_STATUS\n" + " -r,--return return result from method\n" + " -s,--size print table size\n" + " -v,--verbose verbose otuput\n" + " -w,--warn print parser warnings\n" + "\n" + " <what> is one of\n" + " param <PARAM> elements\n" + " info <INFO> elements\n" + " rows table rows\n" + " cols table cols\n" + " resources <RESOURCE> elements\n" + "\n" + " Examples:\n\n" + " 1) Print summary information about a VOTable\n\n" + " %% votinfo -v test.xml\n" + "\n" + " 2) Print the <PARAM> elements in a table, then get a count\n\n" + " %% votinfo -p test.xml\n" + " %% votinfo --numberOf=param test.xml\n" + "\n" + " 3) Determine whether a VOTable contains a successful result\n\n" + " %% votinfo -q test.xml\n\n" + " A zero indicates 'OK', a one is an 'ERR', and -1 means that\n" + " an <INFO> with a 'QUERY_STATUS' was not found\n" + "\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + vo_taskTest (task, "--help", NULL); + + if (access (input, F_OK) != 0) { + fprintf (stderr, "Warning: cannot open file '%s'\n", input); + return; + } + + vo_taskTest (task, "-v", input, NULL); // Ex 1 + vo_taskTest (task, "-p", input, NULL); // Ex 2 + vo_taskTest (task, "--numberOf=param", input, NULL); // Ex 3 + vo_taskTest (task, "--numberOf=info", input, NULL); + vo_taskTest (task, "--numberOf=rows", input, NULL); + vo_taskTest (task, "--numberOf=cols", input, NULL); + vo_taskTest (task, "--numberOf=resource", input, NULL); + + vo_taskTest (task, "-n", "param", input, NULL); + vo_taskTest (task, "-n", "info", input, NULL); + vo_taskTest (task, "-n", "rows", input, NULL); + vo_taskTest (task, "-n", "cols", input, NULL); + vo_taskTest (task, "-n", "resource", input, NULL); + + vo_taskTest (task, "-q", input, NULL); // Ex 4 + + vo_taskTest (task, "-b", input, NULL); + vo_taskTest (task, "-i", input, NULL); + vo_taskTest (task, "-d", input, NULL); + vo_taskTest (task, "-s", input, NULL); + + vo_taskTestReport (self); +} diff --git a/vendor/voclient/voapps/votjoin.c b/vendor/voclient/voapps/votjoin.c new file mode 100644 index 00000000..49853da4 --- /dev/null +++ b/vendor/voclient/voapps/votjoin.c @@ -0,0 +1,203 @@ +/* + * VOTJOIN -- Perform an inner-join of two VOTables. + * + * Usage: + * votjoin [<otps>] <votable> + * + * @file votjoin.c + * @author Mike Fitzpatrick + * @date 6/03/12 + * + * @brief Perform an inner-join of two VOTables. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "votParse.h" /* keep these in order! */ +#include "voApps.h" + + + +/* Global task declarations. These should all be defined as 'static' to + * avoid namespace collisions. + */ +static int vot = 0; /* VOTable handle */ +static int do_return = 0; /* return result? */ + + +/* Result Buffer. + */ +#ifdef USE_RESBUF +#define SZ_RESBUF 8192 + +static char *resbuf; +#endif + + +/* Task specific option declarations. Task options are declared using the + * getopt_long(3) syntax. + */ +int votjoin (int argc, char **argv, size_t *len, void **result); + +static Task self = { "votjoin", votjoin, 0, 0, 0 }; +static char *opts = "hr"; +static struct option long_opts[] = { + { "help", 2, 0, 'h'}, /* --help is std */ + { "return", 2, 0, 'r'}, /* --return is std */ + { "test", 2, 0, '%'}, /* --return is std */ + { NULL, 0, 0, 0 } +}; + + +/* All tasks should declare a static Usage() method to print the help + * text in response to a '-h' or '--help' flag. The help text should + * include a usage summary, a description of options, and some examples. + */ +static void Usage (void); +static void Tests (char *input); + + +/** + * Application entry point. + */ +int +votjoin (int argc, char **argv, size_t *reslen, void **result) +{ + char **pargv, optval[SZ_FNAME]; + char *iname, *oname; + int ch = 0, status = OK, number = 0, pos = 0; + + + /* Initialize result object whether we return an object or not. + */ + *reslen = 0; + *result = NULL; + + /* Initialize local task values. + */ + iname = NULL; + oname = NULL; + vot = -1; + + + /* Parse the argument list. The use of vo_paramInit() is required to + * rewrite the argv[] strings in a way vo_paramNext() can be used to + * parse them. The programmatic interface allows "param=value" to + * be passed in, but the getopt_long() interface requires these to + * be written as "--param=value" so they are not confused with + * positional parameters (i.e. any param w/out a leading '-'). + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + while ((ch = vo_paramNext(opts,long_opts,argc,pargv,optval,&pos)) != 0) { + if (ch > 0) { + /* If the 'ch' value is > 0 we are parsing a single letter + * flag as defined in the 'opts string. + */ + switch (ch) { + case '%': Tests (optval); return (self.nfail); + case 'h': Usage (); return (OK); + case 'n': number++; break; + case 'o': oname = strdup (optval); break; + case 'r': do_return=1; break; + default: + fprintf (stderr, "Invalid option '%s'\n", optval); + return (1); + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + /* This code processes the positional arguments. The 'optval' + * string contains the value but since this string is + * overwritten w/ each arch we need to make a copy (and must + * remember to free it later. + */ + iname = strdup (optval); + break; + } + } + + + /* Sanity checks. Tasks should validate input and accept stdin/stdout + * where it makes sense. + */ + if (iname == NULL) iname = strdup ("stdin"); + if (oname == NULL) oname = strdup ("stdout"); + if (strcmp (iname, "-") == 0) { free (iname), iname = strdup ("stdin"); } + if (strcmp (oname, "-") == 0) { free (oname), oname = strdup ("stdout"); } + + + + + /******** + ******** + ******** + ******** + ******** Main body of task + ******** + ******** + ******** + *******/ + + + + + /* Clean up. Rememebr to free whatever pointers were created when + * parsing arguments. + */ + if (iname) + free (iname); + if (oname) + free (oname); + + vo_paramFree (argc, pargv); + + return (status); /* status must be OK or ERR (i.e. 0 or 1) */ +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "votjoin [<opts>] votable.xml\n\n" + " where\n" + " -%%,--test run unit tests\n" + " -h,--help this message\n" + " -n,--number number output\n" + " -o,--output=<file> output file\n" + " -r,--return return result from method\n" + "\n" + " Examples:\n\n" + " 1) First example\n\n" + " %% votjoin test.xml\n" + "\n" + " 2) Second example\n\n" + " %% votjoin -o pos.txt test.xml\n" + "\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + + /* First argument must always be the 'self' variable, the last must + * always be a NULL to terminate the cmd args. + */ + vo_taskTest (task, "--help", NULL); +} diff --git a/vendor/voclient/voapps/votopic.c b/vendor/voclient/voapps/votopic.c new file mode 100644 index 00000000..990fad18 --- /dev/null +++ b/vendor/voclient/voapps/votopic.c @@ -0,0 +1,268 @@ +/** + * VOTOPIC -- Query VO services by keyword topic + * + * Usage: + * votopic [<opts>] [ <object> | <ra> <dec> ] [ <size> ] + * + * @file votopic.c + * @author Mike Fitzpatrick + * @date 2/03/13 + * + * @brief Query all VO Image services. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "votParse.h" /* keep these in order! */ +#include "voApps.h" + +#define MAX_ARGS 1024 + + +/* Task specific option declarations. Task options are declared using the + * getopt_long(3) syntax. + */ +int voregistry (int argc, char **argv, size_t *len, void **result); +int vodata (int argc, char **argv, size_t *len, void **result); +int votopic (int argc, char **argv, size_t *len, void **result); + +static Task self = { "votopic", votopic, 0, 0, 0 }; +#ifdef USE_OPTS +static char *opts = "%hrs"; +static struct option long_opts[] = { + { "test", 2, 0, '%'}, /* --test is std */ + { "help", 2, 0, 'h'}, /* --help is std */ + { "subject", 2, 0, 's'}, /* subject keywords */ + { "return", 2, 0, 'r'}, /* return result to API */ + { NULL, 0, 0, 0 } +}; +#endif + + +static int debug = 0; /* debug flag */ +static int by_subj = 0; /* subject search */ + +extern void vot_setArg (char **argv, int *argc, char *value); +extern char *vot_mktemp (char *root); +extern int isDecimal (char *val); +extern int isSexagesimal (char *val); + +static void Usage (void); +static void Tests (char *input); + + +/** + * Application entry point. All VOApps tasks MUST contain this + * method signature. + */ +int +votopic (int argc, char **argv, size_t *reslen, void **result) +{ + int i, nres_arg = 0, ndat_arg = 0, status = OK, term = 0; + char *res_argv[MAX_ARGS], *dat_argv[MAX_ARGS], *topic = NULL; + char *resname; + + + memset (res_argv, 0, argc+2); /* initialize */ + memset (dat_argv, 0, argc+2); + resname = vot_mktemp ("votopic"); + + + /* Parse the argument list. + */ + if ((isDecimal (argv[argc-1]) || isSexagesimal (argv[argc-1])) && + (isDecimal (argv[argc-2]) || isSexagesimal (argv[argc-2])) && + (isDecimal (argv[argc-3]) || isSexagesimal (argv[argc-3])) ) + term = argc - 4; + if ((isDecimal (argv[argc-1]) || isSexagesimal (argv[argc-1])) && + !(isDecimal (argv[argc-2]) || isSexagesimal (argv[argc-2])) ) + term = argc - 3; + if (!(isDecimal (argv[argc-1]) || isSexagesimal (argv[argc-1])) ) + term = argc - 2; + + /* Initialize the VOREGISTRY arguments. + */ + vot_setArg (res_argv, &nres_arg, "voregistry"); + + /* Initialize the VODATA arguments. + */ + vot_setArg (dat_argv, &ndat_arg, "vodata"); +#ifdef OLD_METHOD + if (term <= 0) { + fprintf (stderr, "Error: missing <topic> and/or <object> argument\n"); + return (ERR); + } + + for (i=1; i < argc; i++) { + if (i == term) { + vot_setArg (dat_argv, &ndat_arg, resname); + topic = argv[i]; + } else { + if (strcmp(argv[i],"-h")==0 || strcmp(argv[i],"--help")==0) { + Usage (); return (OK); + } else if (strcmp(argv[i],"-%")==0 || strcmp(argv[i],"--test")==0) { + Tests (NULL); return (self.nfail); + } else if (strcmp(argv[i],"-d")==0 || strcmp(argv[i],"--dbg")==0) { + debug++; + + } else if (strcmp(argv[i],"-s")==0 || + strcmp(argv[i],"--subject")==0) { + by_subj++; + } else if ((strcmp(argv[i],"-b")==0 || + strcmp(argv[i],"--bpass")==0) || + (strcmp(argv[i],"-t")==0 || + strcmp(argv[i],"--type")==0)) { + vot_setArg (res_argv, &nres_arg, argv[ i]); /* -b | -t */ + vot_setArg (res_argv, &nres_arg, argv[++i]); /* val */ + } else + vot_setArg (dat_argv, &ndat_arg, argv[i]); + } + } + +#else + for (i=1; i < argc; i++) { + if (strcmp(argv[i],"-h")==0 || strcmp(argv[i],"--help")==0) { + Usage (); return (0); + } else if (strcmp(argv[i],"-%")==0 || strcmp(argv[i],"--test")==0) { + Tests (NULL); return (0); + } else if (strcmp(argv[i],"-d")==0 || strcmp(argv[i],"--dbg")==0) { + debug++; + + } else if (strcmp(argv[i],"-s")==0 || + strcmp(argv[i],"--subject")==0) { + by_subj++; + } else if ((strcmp(argv[i],"-b")==0 || + strcmp(argv[i],"--bpass")==0) || + (strcmp(argv[i],"-t")==0 || + strcmp(argv[i],"--type")==0)) { + vot_setArg (res_argv, &nres_arg, argv[ i]); /* -b | -t */ + vot_setArg (res_argv, &nres_arg, argv[++i]); /* val */ + } else { + if (!topic) { + vot_setArg (dat_argv, &ndat_arg, resname); + topic = argv[i]; + } else { + vot_setArg (dat_argv, &ndat_arg, argv[i]); + } + } + } + + if (topic == NULL) { + fprintf (stderr, "Error: missing <topic> argument\n"); + return (ERR); + } else if (ndat_arg < 3) { + fprintf (stderr, "Error: missing <object> (or <pos>) argument\n"); + return (ERR); + } + +#endif + + + /* Create the list of VOREGISTRY arguments. + */ + vot_setArg (res_argv, &nres_arg, "-d"); /* dalOnly */ + vot_setArg (res_argv, &nres_arg, "-o"); /* output name */ + vot_setArg (res_argv, &nres_arg, resname); + if (by_subj) + vot_setArg (res_argv, &nres_arg, "-s"); + vot_setArg (res_argv, &nres_arg, topic); + + if (debug) { + for (i=0; i < nres_arg; i++) + printf ("'%s' ", res_argv[i]); + printf ("\n"); + for (i=0; i < ndat_arg; i++) + printf ("'%s' ", dat_argv[i]); + printf ("\n"); + } + + + /* Run the Registry query to get the resource list of topics. + */ + status = voregistry (nres_arg, res_argv, reslen, result); + + + /* Initialize result object whether we return an object or not. + */ + *reslen = 0; + *result = NULL; + + /* The VODATA task does all the real work, execute it on the list of + * resources we just obtained. + */ + status = vodata (ndat_arg, dat_argv, reslen, result); + + + /* Clean up. Rememebr to free whatever pointers were created when + * parsing arguments. + */ + for (i=0; i < nres_arg; i++) + if (res_argv[i]); + free ((void *) res_argv[i]); + for (i=0; i < ndat_arg; i++) + if (dat_argv[i]); + free ((void *) dat_argv[i]); + unlink (resname); + + return (status); +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "votopic [<opts>] <topic> { <object> | <ra> <dec> } [ <size> ]\n\n" + " where\n" + " -%%,--test run unit tests\n" + " -h,--help this message\n" + "\n" + "\n" + " Examples:\n\n" + " 1) Query for catalog data of A2712 from Resources related to\n" + " gravitational lensing:\n" + "\n" + " %% votopic -t catalog lens A2712\n" + "\n" + " This query is against only 142 services (data found for 128),\n" + " a similar query against ALL catalog services would require\n" + " more than 8000 services to be queried. This is equivalent to\n" + " the commands:\n" + "\n" + " %% voregistry -t catalog -d -o lens.xml lens\n" + " %% vodata lens.xml A2712\n" + "\n" + " Here the 'lens.xml' output file contains the resources to be\n" + " queried, the '-d' flag says to return only DAL services, the\n" + " '-t' flag resticts by service type. In the call to VODATA,\n" + " the 'lens.xml' file defines the 142 resources to be queried,\n" + " the contraint to service type and DAL-only was done in the\n" + " registry query that produced the file.\n" + "\n" + "\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + + vo_taskTest (task, "--help", NULL); + + vo_taskTest (task, "-t", "catalog", "lens", "A2712", NULL); + + vo_taskTestReport (self); +} diff --git a/vendor/voclient/voapps/votpos.c b/vendor/voclient/voapps/votpos.c new file mode 100644 index 00000000..3b6b3fc9 --- /dev/null +++ b/vendor/voclient/voapps/votpos.c @@ -0,0 +1,249 @@ +/* + * VOTPOS -- Extract the main positional columns from a VOTable. + * + * Usage: + * votpos [<opts>] votable.xml + * + * where + * -%%,--test run unit tests + * -h,--help this message + * -n,--number number output + * -o,--output=<file> output file + * -r,--return return result from method + * + * @file votpos.c + * @author Mike Fitzpatrick + * @date 6/03/12 + * + * @brief Extract the main positional columns from a VOTable. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <ctype.h> + +#include "votParse.h" +#include "voApps.h" + + +#define SZ_RESBUF 8192 + + +static int vot = 0; /* VOTable handle */ +static int number = 0; /* number values? */ +static int do_return = 0; /* return result? */ + +#ifdef USE_RESBUF +static char *resbuf; /* result buffer */ +#endif + + +/* Task specific option declarations. + */ +int votpos (int argc, char **argv, size_t *len, void **result); + +static Task self = { "votpos", votpos, 0, 0, 0 }; +static char *opts = "hNno:r%:"; +static struct option long_opts[] = { + { "Number", 2, 0, 'N'}, /* task option */ + { "number", 2, 0, 'n'}, /* task option */ + { "output", 1, 0, 'o'}, /* task option */ + { "return", 2, 0, 'r'}, /* task option */ + { "help", 2, 0, 'h'}, /* required */ + { "test", 1, 0, '%'}, /* required */ + { NULL, 0, 0, 0 } +}; + + +static void Usage (void); +static void Tests (char *input); + + + +/** + * Application entry point. + */ +int +votpos (int argc, char **argv, size_t *reslen, void **result) +{ + char **pargv, optval[SZ_FNAME], *iname = NULL, *oname = NULL, *ucd = NULL; + int res, tab, data, tdata, field, status = OK; + int i, ncols, nrows, pos = 0, ch, ra_col, dec_col; + int got_ra_col = 0, got_dec_col = 0; + FILE *fd = (FILE *) NULL; + + + /* Initialize. + */ + oname = NULL; + iname = NULL; + *reslen = 0; + *result = NULL; + + /* Parse the argument list. + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + while ((ch = vo_paramNext (opts,long_opts,argc,pargv,optval,&pos)) != 0) { + if (ch > 0) { + switch (ch) { + case '%': Tests (optval); return (self.nfail); + case 'h': Usage (); return (OK); + case 'N': number=-1; break; + case 'n': number=+1; break; + case 'o': oname = strdup (optval); break; + case 'r': do_return=1; break; + default: + fprintf (stderr, "Invalid option '%s'\n", optval); + return (1); + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + iname = strdup (optval); + break; + } + } + + + /* Sanity checks + */ + if (iname == NULL) iname = strdup ("stdin"); + if (oname == NULL) oname = strdup ("stdout"); + if (strcmp (iname, "-") == 0) { free (iname), iname = strdup ("stdin"); } + if (strcmp (oname, "-") == 0) { free (oname), oname = strdup ("stdout"); } + + + /* Open the table. This also parses it. + */ + if ( (vot = vot_openVOTABLE (iname) ) <= 0) { + fprintf (stderr, "Error opening VOTable '%s'\n", iname); + return (1); + } + + res = vot_getRESOURCE (vot); /* get handles */ + if (vot_getLength (res) > 1) { + fprintf (stderr, "Error: multiple RESOURCE elements not supported\n"); + goto clean_up_; + } + tab = vot_getTABLE (res); + if ((data = vot_getDATA (tab))) { + tdata = vot_getTABLEDATA (data); + nrows = vot_getNRows (tdata); + ncols = vot_getNCols (tdata); + } else + goto clean_up_; + + + /* Find the columns. + */ + for (i=0, field=vot_getFIELD(tab); field; field=vot_getNext (field),i++) { + if ((ucd = vot_getAttr (field, "ucd"))) { + if ((strcmp (ucd, "POS_EQ_RA_MAIN") == 0) || /* UCD 1 */ + (strcmp (ucd, "pos.eq.ra;meta.main") == 0)) { /* UCD 1+ */ + ra_col = i; + got_ra_col = 1; + } + if ((strcmp (ucd, "POS_EQ_DEC_MAIN") == 0) || /* UCD 1 */ + (strcmp (ucd, "pos.eq.dec;meta.main") == 0)) { /* UCD 1+ */ + dec_col = i; + got_dec_col = 1; + } + } + } + if (!got_ra_col || !got_dec_col) { + fprintf (stderr, "Error: Cannot find position columns in table.\n"); + status = ERR; + goto clean_up_; + } + + /* Print the position cells. + */ + fd = stdout; + if (strncasecmp ("stdout", oname, 6)) { + if ((fd = fopen (oname, "w+")) == NULL) { + fprintf (stderr, "Error: Cannot open output file '%s'\n", oname); + return (ERR); + } + } + + for (i=0; i < nrows; i++) { + char *ra, *dec, *s; + + s = vot_getTableCell (tdata, i, ra_col); ra = (s ? s : "INDEF"); + s = vot_getTableCell (tdata, i, dec_col); dec = (s ? s : "INDEF"); + if (number > 0) + fprintf (fd, "%d ", i); + fprintf (fd, "%s %s", ra, dec); + if (number < 0) + fprintf (fd, " %d", i); + fprintf (fd, "\n"); + } + + + /* Clean up. + */ +clean_up_: + if (fd != stdout) + fclose (fd); + if (iname) free (iname); + if (oname) free (oname); + + vo_paramFree (argc, pargv); + vot_closeVOTABLE (vot); /* close the table */ + + return (status); +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "votpos [<opts>] votable.xml\n\n" + " where\n" + " -%%,--test run unit tests\n" + " -h,--help this message\n" + " -n,--number number output\n" + " -o,--output=<file> output file\n" + " -r,--return return result from method\n" + "\n" + " Examples:\n\n" + " 1) Print the primary (RA,Dec) columns from a table:\n\n" + " %% votpos test.xml\t\t\t# un-numbered\n" + " %% votpos -n test.xml\t\t# numbered\n" + " %% cat test.xml | votpos\t\t# un-numbered\n" + "\n" + " 2) Print the primary (RA,Dec) columns to a file:\n\n" + " %% votpos -o pos.txt test.xml\n" + "\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + vo_taskTest (task, "--help", NULL); + + vo_taskTest (task, input, NULL); + vo_taskTest (task, "-n", input, NULL); + vo_taskTest (task, "-o", "-", input, NULL); + vo_taskTest (task, "-o", "pos.txt", input, NULL); + + if (access ("pos.txt", F_OK) == 0) unlink ("pos.txt"); + + vo_taskTestReport (self); +} diff --git a/vendor/voclient/voapps/votsort.c b/vendor/voclient/voapps/votsort.c new file mode 100644 index 00000000..12945e83 --- /dev/null +++ b/vendor/voclient/voapps/votsort.c @@ -0,0 +1,394 @@ +/* + * VOTSORT -- Sort a VOTable based on a column value. + * + * Usage: + * votsort [<otps>] <votable.xml> + * + * Where + * -c,--col <N> Sort column num + * -d,--desc Sort in descending order + * -f,--fmt <format> Output format + * -o,--output <name> Output name + * -s,--string String sort + * -t,--top <N> Print top <N> rows + * -i,--indent <N> XML indent level + * -n,--noheader Suppress header + * -N,--name <name> Find <name> column + * -I,--id <id> Find <id> column + * -U,--ucd <ucd> Find <ucd> column + * + * -h,--help This message + * -r,--return Return result + * -%,--test Run unit tests + * + * @file votsort.c + * @author Mike Fitzpatrick + * @date 6/03/12 + * + * @brief Sort a VOTable based on a column. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "votParse.h" /* keep these in order! */ +#include "voApps.h" + + +static int do_return = 0; /* return result? */ +static int sort_order = 1; /* ascending order */ +static int top = 0; /* top results (0 for all) */ + + + +/* A result buffer should be defined to point to the result object if it is + * created dynamically, e.g. a list of votable columns. The task is + * responsible for initially allocating this pointer and then resizing as + * needed. + */ +#ifdef USE_RESBUF +#define SZ_RESBUF 8192 + +static char *resbuf; +#endif + + +/* Task specific option declarations. Task options are declared using the + * getopt_long(3) syntax. + */ +int votsort (int argc, char **argv, size_t *len, void **result); + +static Task self = { "votsort", votsort, 0, 0, 0 }; +static char *opts = "%:c:df:hi:LnN:I:U:o:rst:"; +static struct option long_opts[] = { + { "col", 1, 0, 'c'}, /* sort column num */ + { "desc", 2, 0, 'd'}, /* sort in descending order */ + { "fmt", 1, 0, 'f'}, /* output format */ + { "output", 1, 0, 'o'}, /* output name */ + { "string", 2, 0, 's'}, /* string sort */ + { "top", 1, 0, 't'}, /* string sort */ + { "indent", 1, 0, 'i'}, /* xml indent level */ + { "noheader", 2, 0, 'n'}, /* suppress header */ + { "name", 1, 0, 'N'}, /* find <name> column */ + { "id", 1, 0, 'I'}, /* find <id> column */ + { "ucd", 1, 0, 'U'}, /* find <ucd> column */ + + { "help", 2, 0, 'h'}, /* --help is std */ + { "return", 2, 0, 'r'}, /* --return is std */ + { "test", 1, 0, '%'}, /* --test is std */ + { NULL, 0, 0, 0 } +}; + + +/* All tasks should declare a static Usage() method to print the help + * text in response to a '-h' or '--help' flag. The help text should + * include a usage summary, a description of options, and some examples. + */ +static void Usage (void); +static void Tests (char *input); + +extern int vot_isNumericField (handle_t field); +extern int vot_isValidFormat (char *fmt); +extern int vot_atoi (char *val); +extern int strdic (char *in_str, char *out_str, int maxchars, char *dict); + + + +/** + * Application entry point. All VOApps tasks MUST contain this + * method signature. + */ +int +votsort (int argc, char **argv, size_t *reslen, void **result) +{ + /* These declarations are required for the VOApps param interface. + */ + char **pargv, optval[SZ_FNAME], format[SZ_FORMAT]; + char *iname, *oname, *fmt = NULL; + char *byName = NULL, *byID = NULL, *byUCD = NULL; + int i = 0, ch = 0, status = OK, pos = 0, col = -1, do_string = 0; + int vot, res, tab, data, tdata, field, tr; + int indent = 0, scalar = 0, hdr = 1; + + + /* Initialize result object whether we return an object or not. + */ + *reslen = 0; + *result = NULL; + + /* Initialize local task values. + */ + iname = NULL; + oname = NULL; + + + /* Parse the argument list. The use of vo_paramInit() is required to + * rewrite the argv[] strings in a way vo_paramNext() can be used to + * parse them. The programmatic interface allows "param=value" to + * be passed in, but the getopt_long() interface requires these to + * be written as "--param=value" so they are not confused with + * positional parameters (i.e. any param w/out a leading '-'). + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + while ((ch = vo_paramNext(opts,long_opts,argc,pargv,optval,&pos)) != 0) { + if (ch > 0) { + /* If the 'ch' value is > 0 we are parsing a single letter + * flag as defined in the 'opts string. + */ + switch (ch) { + case '%': Tests (optval); return (self.nfail); + case 'h': Usage (); return (OK); + case 'c': col = vot_atoi (optval); break; + case 'd': sort_order = -1; break; + case 'f': if (!vot_isValidFormat ((fmt = strdup (optval)))) { + fprintf (stderr, "Error: invalid format '%s'\n", + fmt); + return (ERR); + } + break; + case 'o': oname = strdup (optval); break; + case 'i': indent = vot_atoi (optval); break; + case 'n': hdr=0; break; + case 'N': byName = strdup (optval); break; + case 'I': byID = strdup (optval); break; + case 'U': byUCD = strdup (optval); break; + case 'r': do_return = 1; break; + case 's': do_string = 1; break; + case 't': top = vot_atoi (optval); break; + default: + fprintf (stderr, "Invalid option '%s'\n", optval); + return (1); + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + /* This code processes the positional arguments. The 'optval' + * string contains the value but since this string is + * overwritten w/ each arch we need to make a copy (and must + * remember to free it later). + */ + iname = strdup (optval); + break; /* only allow one file */ + } + } + + + /* Sanity checks. Tasks should validate input and accept stdin/stdout + * where it makes sense. + */ + if (iname == NULL) iname = strdup ("stdin"); + if (oname == NULL) oname = strdup ("stdout"); + if (strcmp (iname, "-") == 0) { free (iname), iname = strdup ("stdin"); } + if (strcmp (oname, "-") == 0) { free (oname), oname = strdup ("stdout"); } + + fmt = (fmt ? fmt : strdup ("xml")); + + + /* Open the table. This also parses it. + */ + if ( (vot = vot_openVOTABLE (iname) ) <= 0) { + fprintf (stderr, "Error opening VOTable '%s'\n", iname); + return (1); + } + + res = vot_getRESOURCE (vot); /* get handles */ + if (vot_getLength (res) > 1) { + fprintf (stderr, "Error: multiple RESOURCE elements not supported\n"); + goto clean_up_; + } + if ((tab = vot_getTABLE (res)) <= 0) + goto clean_up_; + if ((data = vot_getDATA (tab))) + tdata = vot_getTABLEDATA (data); + else + goto clean_up_; + + + /* Find the requested sort column. If the column isn't set explicitly + * check each field for the name/id/ucd. + */ + if (col < 0) { + char *name, *id, *ucd; + handle_t field; + + for (field=vot_getFIELD(tab); field; field=vot_getNext(field),i++) { + id = vot_getAttr (field, "id"); + name = vot_getAttr (field, "name"); + ucd = vot_getAttr (field, "ucd"); + + /* See whether this is a column we can sort numerically. + */ + if (! do_string) + scalar = vot_isNumericField (field); + + if ((byName && name && strcasecmp (name, byName) == 0) || + (byID && id && strcasecmp (id, byID) == 0) || + (byUCD && ucd && strcasecmp (ucd, byUCD) == 0)) { + col = i, do_string = (do_string ? 1 : ! scalar); + break; + } + } + + } else { + register int i = 0; + + for (field = vot_getFIELD(tab); field && i < col; i++) + field = vot_getNext(field); + if (! do_string) + scalar = vot_isNumericField (field); + do_string = (do_string ? 1 : ! scalar); + } + + + /* Sort the table. + */ + (void) vot_sortTable (tdata, (col < 0 ? 0 : col), do_string, sort_order); + + + /* Now trim the data rows if we've set a TOP condition. + */ + if (top) { + int row = 0, ntr = 0; + + /* Skip over the rows we'll keep + */ + for (tr=vot_getTR (tdata); tr && row < top; tr=vot_getNext(tr)) + row++; + + /* Free the remaining rows. + */ + for ( ; tr; tr = ntr) { + ntr=vot_getNext(tr); + vot_deleteNode (tr); + } + } + + + /* Output the new format. + */ + memset (format, 0, SZ_FORMAT); + switch (strdic (fmt, format, SZ_FORMAT, FORMATS)) { + case VOT: vot_writeVOTable (vot, oname, indent); break; + case ASV: vot_writeASV (vot, oname, hdr); break; + case BSV: vot_writeBSV (vot, oname, hdr); break; + case CSV: vot_writeCSV (vot, oname, hdr); break; + case TSV: vot_writeTSV (vot, oname, hdr); break; + case HTML: vot_writeHTML (vot, iname, oname); break; + case SHTML: vot_writeSHTML (vot, iname, oname); break; + case FITS: vot_writeFITS (vot, oname); break; + case ASCII: vot_writeASV (vot, oname, hdr); break; + case XML: vot_writeVOTable (vot, oname, indent); break; + case RAW: vot_writeVOTable (vot, oname, indent); break; + default: + fprintf (stderr, "Unknown output format '%s'\n", fmt); + status = ERR; + } + + + /* Clean up. Rememebr to free whatever pointers were created when + * parsing arguments. + */ +clean_up_: + if (iname) free (iname); + if (oname) free (oname); + if (fmt) free (fmt); + if (byID) free (byID); + if (byUCD) free (byUCD); + if (byName) free (byName); + + vo_paramFree (argc, pargv); + vot_closeVOTABLE (vot); + + return (status); /* status must be OK or ERR (i.e. 0 or 1) */ +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "votsort [<opts>] votable.xml\n\n" + " Where\n" + " -c,--col <N> Sort column num\n" + " -d,--desc Sort in descending order\n" + " -f,--fmt <format> Output format\n" + " -o,--output <name> Output name\n" + " -s,--string String sort\n" + " -t,--top <N> Print top <N> rows\n" + " -i,--indent <N> XML indent level\n" + " -n,--noheader Suppress header\n" + " -N,--name <name> Find <name> column\n" + " -I,--id <id> Find <id> column\n" + " -U,--ucd <ucd> Find <ucd> column\n" + "\n" + " -h,--help This message\n" + " -r,--return Return result\n" + " -%%,--test Run unit tests\n" + "\n" + " <format> is one of\n" + " vot A new VOTable\n" + " asv ascii separated values\n" + " bsv bar separated values\n" + " csv comma separated values\n" + " tsv tab separated values\n" + " html standalone HTML document\n" + " shtml single HTML <table>\n" + " fits FITS binary table\n" + " ascii ASV alias\n" + " xml VOTable alias\n" + " raw VOTable alias\n" + "\n" + "\n" + " Examples:\n\n" + " 1) Sort a VOTable based on first column\n\n" + " %% votsort test.xml\n" + " %% votsort http://generic.edu/test.xml\n" + " %% cat test.xml | votsort -o sort_test.xml\n" + "\n" + " A string sort will be done automatically if this is a\n" + " string-valued column, otherwise a numeric sort is done.\n" + "\n" + " 2) Sort a VOTable based on the magnitude column\n\n" + " %% votsort --name=id test.xml\n" + "\n" + " 3) Same as above, select 10 faintest stars\n\n" + " %% votsort --name=id --desc --top=10 test.xml\n" + "\n" + " 4) String sort based on object name, output as CSV\n\n" + " %% votsort -s -f csv test.xml\n" + " %% votsort --string --fmt=csv test.xml\n" + "\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + vo_taskTest (task, "--help", NULL); + + vo_taskTest (task, input, NULL); // Ex 1 + vo_taskTest (task, "http://iraf.noao.edu/votest/sort.xml", NULL); // Ex 2 + vo_taskTest (task, "--name=id", input, NULL); // Ex 3 + vo_taskTest (task, "--name=id", "--desc", "--top=10", input, NULL); // Ex 4 + vo_taskTest (task, "-s", "-f", "csv", input, NULL); // Ex 5 + vo_taskTest (task, "--string", "--fmt=csv", input, NULL); // Ex 6 + + vo_taskTest (task, "--name=id", "-s", "--desc", "--fmt=csv", input, NULL); + + vo_taskTestReport (self); +} + diff --git a/vendor/voclient/voapps/votsplit.c b/vendor/voclient/voapps/votsplit.c new file mode 100644 index 00000000..9e4695c3 --- /dev/null +++ b/vendor/voclient/voapps/votsplit.c @@ -0,0 +1,202 @@ +/* + * VOTSPLIT -- Split a Multi-RESOURCE VOTable into single tables. + * + * Usage: + * votsplit [<otps>] <votable> + * + * @file votsplit.c + * @author Mike Fitzpatrick + * @date 6/03/12 + * + * @brief Split a Multi-RESOURCE VOTable into single tables. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "votParse.h" /* keep these in order! */ +#include "voApps.h" + + + +/* Global task declarations. These should all be defined as 'static' to + * avoid namespace collisions. + */ +static int vot = 0; /* VOTable handle */ +static int do_return = 0; /* return result? */ + + +/* Result Buffer. + */ +#ifdef USE_RESBUF +#define SZ_RESBUF 8192 + +static char *resbuf; +#endif + + +/* Task specific option declarations. Task options are declared using the + * getopt_long(3) syntax. + */ +int votsplit (int argc, char **argv, size_t *len, void **result); + +static Task self = { "votsplit", votsplit, 0, 0, 0 }; +static char *opts = "hr"; +static struct option long_opts[] = { + { "help", 2, 0, 'h'}, /* --help is std */ + { "return", 2, 0, 'r'}, /* --return is std */ + { "test", 2, 0, '%'}, /* --return is std */ + { NULL, 0, 0, 0 } +}; + + +/* All tasks should declare a static Usage() method to print the help + * text in response to a '-h' or '--help' flag. The help text should + * include a usage summary, a description of options, and some examples. + */ +static void Usage (void); +static void Tests (char *input); + + +/** + * Application entry point. + */ +int +votsplit (int argc, char **argv, size_t *reslen, void **result) +{ + char **pargv, optval[SZ_FNAME]; + char *iname, *oname; + int ch = 0, status = OK, number = 0, pos = 0; + + + /* Initialize result object whether we return an object or not. + */ + *reslen = 0; + *result = NULL; + + /* Initialize local task values. + */ + iname = NULL; + oname = NULL; + vot = -1; + + + /* Parse the argument list. The use of vo_paramInit() is required to + * rewrite the argv[] strings in a way vo_paramNext() can be used to + * parse them. The programmatic interface allows "param=value" to + * be passed in, but the getopt_long() interface requires these to + * be written as "--param=value" so they are not confused with + * positional parameters (i.e. any param w/out a leading '-'). + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + while ((ch = vo_paramNext(opts,long_opts,argc,pargv,optval,&pos)) != 0) { + if (ch > 0) { + /* If the 'ch' value is > 0 we are parsing a single letter + * flag as defined in the 'opts string. + */ + switch (ch) { + case '%': Tests (optval); return (self.nfail); + case 'h': Usage (); return (OK); + case 'n': number++; break; + case 'o': oname = strdup (optval); break; + case 'r': do_return=1; break; + default: + fprintf (stderr, "Invalid option '%s'\n", optval); + return (1); + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + /* This code processes the positional arguments. The 'optval' + * string contains the value but since this string is + * overwritten w/ each arch we need to make a copy (and must + * remember to free it later. + */ + iname = strdup (optval); + break; + } + } + + + /* Sanity checks. Tasks should validate input and accept stdin/stdout + * where it makes sense. + */ + if (iname == NULL) iname = strdup ("stdin"); + if (oname == NULL) oname = strdup ("stdout"); + if (strcmp (iname, "-") == 0) { free (iname), iname = strdup ("stdin"); } + if (strcmp (oname, "-") == 0) { free (oname), oname = strdup ("stdout"); } + + + + + /******** + ******** + ******** + ******** + ******** Main body of task + ******** + ******** + ******** + *******/ + + + + + /* Clean up. Rememebr to free whatever pointers were created when + * parsing arguments. + */ + if (iname) + free (iname); + if (oname) + free (oname); + + vo_paramFree (argc, pargv); + + return (status); /* status must be OK or ERR (i.e. 0 or 1) */ +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "votsplit [<opts>] votable.xml\n\n" + " where\n" + " -%%,--test run unit tests\n" + " -h,--help this message\n" + " -n,--number number output\n" + " -o,--output=<file> output file\n" + " -r,--return return result from method\n" + "\n" + " Examples:\n\n" + " 1) First example\n\n" + " %% votsplit test.xml\n" + "\n" + " 2) Second example\n\n" + " %% votsplit -o pos.txt test.xml\n" + "\n" + ); +} + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + /* First argument must always be the 'self' variable, the last must + * always be a NULL to terminate the cmd args. + */ + vo_taskTest (task, "--help", NULL); +} diff --git a/vendor/voclient/voapps/votstat.c b/vendor/voclient/voapps/votstat.c new file mode 100644 index 00000000..0065e314 --- /dev/null +++ b/vendor/voclient/voapps/votstat.c @@ -0,0 +1,281 @@ +/* + * VOTSTAT -- Compute statistics for numeric columns of a VOTable. + * + * Usage: + * votstat [<otps>] <votable> + * + * @file votstat.c + * @author Mike Fitzpatrick + * @date 6/03/12 + * + * @brief Compute statistics for numeric columns of a VOTable. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <math.h> + +#include "votParse.h" /* keep these in order! */ +#include "voApps.h" + + + +/* Global task declarations. + */ +static int vot = 0; /* VOTable handle */ + +static int do_all = 0; /* all columns? */ +static int do_return = 0; /* return result? */ + + +/* A result buffer should be defined to point to the result object if it is + * created dynamically, e.g. a list of votable columns. The task is + * responsible for initially allocating this pointer and then resizing as + * needed. + */ +#ifdef USE_RESBUF +#define SZ_RESBUF 8192 + +static char *resbuf; +#endif + + +/* Task specific option declarations. Task options are declared using the + * getopt_long(3) syntax. + */ +int votstat (int argc, char **argv, size_t *len, void **result); + +static Task self = { "votstat", votstat, 0, 0, 0 }; +static char *opts = "%:hao:r"; +static struct option long_opts[] = { + { "test", 1, 0, '%'}, + { "help", 2, 0, 'h'}, + { "all", 2, 0, 'a'}, + { "output", 1, 0, 'o'}, + { "return", 2, 0, 'r'}, + { NULL, 0, 0, 0 } +}; + + +/* Standard usage method. + */ +static void Usage (void); +static void Tests (char *input); + +void vot_colStat (int tdata, int col, int nrows, double *min, double *max, + double *mean, double *stddev); + +extern int vot_isNumericField (handle_t field); +extern double vot_atof (char *v); + + +/** + * Application entry point. + */ +int +votstat (int argc, char **argv, size_t *reslen, void **result) +{ + /* These declarations are required for the VOApps param interface. + */ + char **pargv, optval[SZ_FNAME]; + + /* These declarations are specific to the task. + */ + char *iname, *oname, *name, *id, *fstr; + int ch = 0, status = OK, numeric = 0; + int res, tab, data, tdata, field; + int i, ncols, nrows, pos = 0; + FILE *fd = (FILE *) NULL; + + + /* Initialize result object whether we return an object or not. + */ + *reslen = 0; + *result = NULL; + + iname = NULL; /* initialize local task values */ + oname = NULL; + + + /* Parse the argument list. + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + while ((ch = vo_paramNext(opts,long_opts,argc,pargv,optval,&pos)) != 0) { + if (ch > 0) { + switch (ch) { + case '%': Tests (optval); return (self.nfail); + case 'h': Usage (); return (OK); + case 'a': do_all++; break; + case 'o': oname = strdup (optval); break; + case 'r': do_return=1; break; + default: + fprintf (stderr, "Invalid option '%s'\n", optval); + return (1); + } + + } else if (ch == PARG_ERR) { + return (ERR); + + } else { + /* Process the positional arguments. + */ + iname = strdup (optval); + break; + } + } + + + /* Sanity checks. Tasks should validate input and accept stdin/stdout + * where it makes sense. + */ + if (iname == NULL) iname = strdup ("stdin"); + if (oname == NULL) oname = strdup ("stdout"); + if (strcmp(iname, "-") == 0) { free (iname), iname = strdup ("stdin"); } + if (strcmp(oname, "-") == 0) { free (oname), oname = strdup ("stdout"); } + + if (strcmp ("stdout", oname) == 0) + fd = stdout; + else { + if ((fd = fopen (oname, "w+")) == (FILE *) NULL) { + fprintf (stderr, "Cannot open output file '%s'\n", oname); + return (ERR); + } + } + + /* Open the table. This also parses it. + */ + if ( (vot = vot_openVOTABLE (iname) ) <= 0) { + fprintf (stderr, "Error opening VOTable '%s'\n", iname); + return (1); + } + + res = vot_getRESOURCE (vot); /* get handles */ + if (vot_getLength (res) > 1) { + fprintf (stderr, "Error: multiple RESOURCE elements not supported\n"); + goto clean_up_; + } + tab = vot_getTABLE (res); + if ((data = vot_getDATA (tab)) <= 0) + goto clean_up_; + tdata = vot_getTABLEDATA (data); + nrows = vot_getNRows (tdata); + ncols = vot_getNCols (tdata); + + + fprintf (fd, "# %3s %-20.20s %9.9s %9.9s %9.9s %9.9s\n#\n", + "Col", "Name", "Min", "Max", "Mean", "StdDev"); + + for (i=0,field=vot_getFIELD(tab); field; field=vot_getNext (field), i++) { + name = vot_getAttr (field, "name"); + id = vot_getAttr (field, "id"); + + numeric = vot_isNumericField (field); + fstr = (name ? name : (id ? id : "(none)")); + + if (do_all && !numeric) /* non-numeric column */ + fprintf (fd, " %3d %-20.20s\n", i, fstr); + + else if (do_all || numeric) { /* numeric column */ + double min, max, mean, stddev; + + vot_colStat (tdata, i, nrows, &min, &max, &mean, &stddev); + + if (mean > 1.0e6 || mean < 1.0e-3) + fprintf (fd, " %3d %-20.20s %9.4g %9.4g %9.4g %9.4g\n", + i, fstr, min, max, mean, stddev); + else + fprintf (fd, " %3d %-20.20s %9.2f %9.2f %9.2f %9.2f\n", + i, fstr, min, max, mean, stddev); + } + } + + + /* Clean up. Rememebr to free whatever pointers were created when + * parsing arguments. + */ +clean_up_: + if (iname) free (iname); + if (oname) free (oname); + + vo_paramFree (argc, pargv); + vot_closeVOTABLE (vot); + + if (fd != stdout) + fclose (fd); + + return (status); /* status must be OK or ERR (i.e. 0 or 1) */ +} + + +/** + * VOT_COLSTAT -- Determine the statistics of a table column. + */ +void +vot_colStat (int tdata, int col, int nrows, double *min, double *max, + double *mean, double *stddev) +{ + register int i = 0; + double sum = 0.0, sum2 = 0.0, val = 0.0; + + + *min = 0.99e306; + *max = -0.99e306; + *mean = 0.0; + *stddev = 0.0; + + for (i=0; i < nrows; i++) { + val = vot_atof (vot_getTableCell (tdata, i, col)); + sum += val; + sum2 += (val * val); + if (val < (*min)) *min = val; + if (val > (*max)) *max = val; + } + + *mean = (double) (sum / (double) nrows); + *stddev = sqrt ( ( sum2 / (double) nrows) - + ( (sum / (double) nrows) * (sum / (double) nrows) )); +} + + +/** + * USAGE -- Print task help summary. + */ +static void +Usage (void) +{ + fprintf (stderr, "\n Usage:\n\t" + "votstat [<opts>] votable.xml\n\n" + " where\n" + " -h,--help this message\n" + " -%%,--test run unit tests\n" + " -r,--return return result from method\n" + "\n" + " -a,--all print all columns\n" + " -o,--output=<file> output file\n" + "\n" + " Examples:\n\n" + " 1) Print statistics for a VOTable\n\n" + " %% votstat test.xml\n" + "\n" + " 2) Print statistics for all column in a VOTable and save \n" + " results to a file.\n\n" + " %% votstat -a -o stats test.xml\n" + "\n" + ); +} + + + +/** + * Tests -- Task unit tests. + */ +static void +Tests (char *input) +{ + Task *task = &self; + + vo_taskTest (task, "--help", NULL); +} diff --git a/vendor/voclient/voapps/zzparam.c b/vendor/voclient/voapps/zzparam.c new file mode 100644 index 00000000..fd856021 --- /dev/null +++ b/vendor/voclient/voapps/zzparam.c @@ -0,0 +1,87 @@ +/** + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <getopt.h> +#include <string.h> +#include <errno.h> +#include "voApps.h" + + +char optval[128]; + +/* Task specific option declarations. + */ +char *opts = "abn:v:"; +struct option long_opts[] = { + { "debug", 0, 0, 'd'}, + { "nport", 1, 0, 'n'}, + { "verbose", 2, 0, 'v'}, + { NULL, 0, 0, 0 } +}; + + + +/* + * -v + * -v 0 + * -v=0 + * --verbose + * --verbose 0 + * --verbose=0 + * verbose=0 +*/ + +int ch=0, all=0, debug=0, verbose=0, nport=0; + +int +main (int argc, char *argv[]) +{ + int i, pos; + char **pargv; + + + /* Initialize the parameters, i.e. rewrite the options so they can + * be processed by getopt_long(). + */ + pargv = vo_paramInit (argc, argv, opts, long_opts); + while ((ch = vo_paramNext (opts,long_opts,argc,pargv,optval,&pos)) != 0) { + if (ch > 0) { + switch (ch) { + case 'a': printf ("'a' key\n"); + break; + case 'd': printf ("'d' key\n"); + break; + case 'n': printf ("'n' key, arg '%s'\n", optval); + nport = atoi (optval); + break; + case 'v': + if (optval[0]) { + printf ("'v' key, arg = '%s'\n", optval); + verbose = atoi (optval); + } else { + printf ("'v' key\n"); verbose = 1; + } + break; + default: + printf ("\nDEFAULT\n"); + } + + } else if (ch == PARG_ERR) { + return (1); + + } else + printf ("pos=%d optind=%d argc=%d val='%s'\n", + pos, optind, argc, optval); + } + + printf ("\n\n"); + printf ("final nport = %d\n", nport); + printf ("final verbose = %d\n", verbose); + + + /* Free the allocated arguments. + */ + vo_paramFree (argc, pargv); +} diff --git a/vendor/voclient/voapps/zztest.c b/vendor/voclient/voapps/zztest.c new file mode 100644 index 00000000..ff5add17 --- /dev/null +++ b/vendor/voclient/voapps/zztest.c @@ -0,0 +1,427 @@ + + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include "votParse.h" + + + +typedef struct colum { + char name[100]; + char ucd[1000]; +} col_t; + +int +pseudocode1(char *fname) +{ + handle_t vot, res, data, tab, field, tr, td, fits, stream, tdata, + bin; + int nrows, ncols, i, l, m, use_direct = 1; + char *str, *extnum, *href, *ucd, *name; + + printf("--------------Test 1-------------------------------------------\n"); + + col_t *col; + + vot = vot_openVOTABLE(fname); + + /* Loop over RESOURCES. */ + res = vot_getRESOURCE(vot); + + printf("Table has toplevel %i RESOURCE elements\n", + vot_getLength(res)); + + while (res) { + tab = vot_getTABLE(res); + + /* Print column info. */ + + /* Get the data element. */ + data = vot_getDATA(tab); + + /* Get data stored as a TABLEDATA XML block. */ + tdata = vot_getTABLEDATA(data); + + col = (col_t *) calloc(vot_getNCols(tdata), sizeof(col_t)); + + for (field = vot_getFIELD(tab), i = 0; field; field = vot_getNext(field), i++) { + name = vot_getAttr(field, "name"); + ucd = vot_getAttr(field, "ucd"); + + if (name != NULL) + strcpy(col[i].name, name); + + if (ucd != NULL) + strcpy(col[i].ucd, ucd); + + printf("%s, ", col[i].name); + } + + printf("\n"); + + switch (vot_getDATAType(data)) { + case TY_TABLEDATA: + + if (use_direct) { + /* Get the table data cells by direct index. */ + tr = vot_getTR(tdata); + nrows = vot_getLength(tr); + ncols = vot_getLength(vot_getTD(tr)); + + for (l = 0; l < nrows; l++) { + for (m = 0; m < ncols; m++) { + str = vot_getTableCell(tdata, l, m); + printf("%s\n", str); + } + + printf("--\n"); + } + } else { + /* Get the table data cells by looping over rows/cols. */ + for (tr = vot_getTR(tdata); tr; tr = vot_getNext(tr)) { + for (td = vot_getTD(tr); td; td = vot_getNext(td)) { + str = vot_getValue(td); + printf("%s\n", str); + } + } + } + + break; + + case TY_BINARY: + /* + * Get data stored as inline binary. If the encoding of the + * stream is based64 read the sequence of bytes and decode. + */ + + bin = vot_getBINARY(data); + stream = vot_getSTREAM(bin); + + if (strcasecmp("base64", vot_getAttr(stream, "encoding")) == 0) + str = vot_getValue(stream); + printf("%s\n", str); + + break; + + case TY_FITS: + /* + * Read FITS data. Assumes a particular extension of an MEF is + * avaliable for download at the given href. + */ + fits = vot_getFITS(data); + extnum = vot_getAttr(fits, "extnum"); + + stream = vot_getSTREAM(fits); + href = vot_getAttr(stream, "href"); + + /* Download the FITS file. */ + + break; + + default: + printf("Error: Invalid table DATA type.\n"); + } + + res = vot_getNext(res); + } + + + printf("--------------\\Test 1-----------------------------------------\n"); + + return (0); + +} + +int +pseudocode2(char *fname) +{ + handle_t vot, res, p; + + printf("--------------Test 2-------------------------------------------\n"); + vot = vot_openVOTABLE(fname); + + res = vot_getRESOURCE(vot); + + for (p = vot_getChild(res); p; p = vot_getSibling(p)) { + if (vot_typeOf(p) == TY_PARAM) + printf("PARAM name=%s value=%s\n", + vot_getAttr(p, "name"), vot_getAttr(p, "value")); + } + + printf("\n"); + res = vot_getRESOURCE(vot); + + for (p = vot_getPARAM(res); p; p = vot_getNext(p)) { + printf("PARAM name=%s value=%s\n", + vot_getAttr(p, "name"), vot_getAttr(p, "value")); + } + + + printf("------------\\Test 2-------------------------------------------\n"); + + return (0); +} + +int +pseudocode3(char *fname) +{ + handle_t vot, res, param, info; + + printf("--------------Test 3-------------------------------------------\n"); + vot = vot_openVOTABLE(fname); + + if ((info = vot_getINFO(vot))) { + if (strcasecmp(vot_getAttr(info, "name"), "error") == 0) + printf("ERROR: VALUE=%s\n", vot_getAttr(info, "value")); + } else { + printf("File OK.\n"); + } + + + vot = vot_openVOTABLE(fname); + res = vot_getRESOURCE(vot); + param = vot_getPARAM(res); + info = vot_getINFO(res); + + if ((param) && strcasecmp(vot_getAttr(param, "name"), "error") == 0) { + /* SCS alternate method where PARAN defines value the error string. */ + printf("ERROR: VALUE=%s\n", vot_getAttr(param, "value")); + } else if ((info) && strcasecmp(vot_getAttr(info, "name"), "QUERY_STATUS") == 0) { + /* + * All-other DAL methods where PARAM and INFO of the RESOURCE defines + * a QUERY_STATUS of the result. + */ + if (strcasecmp(vot_getAttr(info, "value"), "OK") == 0) + printf("FILE OK.\n"); + else + printf("ERROR: Value=%s\n", vot_getValue(info)); + } else + printf("FILE OK.\n"); + + + printf("------------\\Test 3-------------------------------------------\n"); + return (0); +} + +int +pseudocode4(void) +{ + handle_t vot, res, data, tab, f, tr, td, tdata, desc, info; + int nrows = 5, ncols = 10, i, j; + char colname[50]; + char **data_m; + char **ip; + char *tmpstr; + + printf("--------------Test 4-------------------------------------------\n"); + + data_m = (char **) calloc((nrows * ncols), sizeof(char *)); + + ip = data_m; + + for (i = 0; i < nrows; i++) { + for (j = 0; j < ncols; j++) { + tmpstr = (char *) calloc(30, sizeof(char)); + sprintf(tmpstr, "row: %i, col: %i", i, j); + *ip++ = tmpstr; + } + } + + + vot = vot_openVOTABLE(NULL); + + res = vot_newNode(vot, TY_RESOURCE); + vot_setAttr(res, "id", "newtable"); + + desc = vot_newNode(vot, TY_DESCRIPTION); + vot_setValue(desc, "This is a test description."); + + tab = vot_newNode(res, TY_TABLE); + + for (i = 0; i < 10; i++) { + f = vot_newNode(tab, TY_FIELD); + sprintf(colname, "col%d", i); + vot_setAttr(f, "name", colname); + vot_setAttr(f, "id", colname); + } + + data = vot_newNode(tab, TY_DATA); + tdata = vot_newNode(data, TY_TABLEDATA); + + for (i = 0; i < nrows; i++) { + tr = vot_newNode(tdata, TY_TR); + for (j = 0; j < ncols; j++) { + td = vot_newNode(tr, TY_TD); + vot_setValue(td, (char *) data_m[(i * ncols) + j]); + } + } + + info = vot_newNode(tab, TY_INFO); + vot_setAttr(info, "id", "STATUS"); + vot_setAttr(info, "value", "OK"); + + vot_writeVOTable(vot, "stdout", 1); + + + printf("------------\\Test 4-------------------------------------------\n"); + + return (0); +} + +int +pseudocode5_copy(char *fname1, char *fname2) +{ + handle_t vot2, res2, cres2; + handle_t vot1, res1, cres1; + handle_t vot3; + + printf("--------------Test 5-------------------------------------------\n"); + + vot1 = vot_openVOTABLE(fname1); + printf("Handles: %i\n", vot_handleCount()); + vot2 = vot_openVOTABLE(fname2); + printf("Handles: %i\n", vot_handleCount()); + + res1 = vot_getRESOURCE(vot1); + res2 = vot_getRESOURCE(vot2); + + cres1 = vot_copyElement(res1, 0); + cres2 = vot_copyElement(res2, 0); + printf("Handles: %i\n", vot_handleCount()); + + vot3 = vot_openVOTABLE(NULL); + + vot_attachNode(vot3, cres1); + vot_attachNode(vot3, cres2); + + vot_writeVOTable(vot3, "stdout", 1); + + printf("Handles: %i\n", vot_handleCount()); + vot_closeVOTABLE(vot1); + vot_closeVOTABLE(vot2); + vot_closeVOTABLE(vot3); + vot_closeVOTABLE(cres2); + vot_closeVOTABLE(cres1); + printf("Handles: %i\n", vot_handleCount()); + vot_deleteNode(cres2); + vot_deleteNode(cres1); + printf("Handles: %i\n", vot_handleCount()); + vot_writeVOTable(vot3, "stdout", 1); + + printf("------------\\Test 5-------------------------------------------\n"); + return (0); +} + +int +pseudocode5(char *fname1, char *fname2) +{ + handle_t vot2, res2; + handle_t vot1, res1; + handle_t vot3; + + printf("--------------Test 5-------------------------------------------\n"); + + vot1 = vot_openVOTABLE(fname1); + vot2 = vot_openVOTABLE(fname2); + + res1 = vot_getRESOURCE(vot1); + res2 = vot_getRESOURCE(vot2); + + vot3 = vot_openVOTABLE(NULL); + + vot_attachNode(vot3, res1); + vot_attachNode(vot3, res2); + + vot_writeVOTable(vot3, "stdout", 1); + printf("Handles: %i\n", vot_handleCount()); + vot_closeVOTABLE(vot1); + printf("Handles: %i\n", vot_handleCount()); + vot_closeVOTABLE(vot2); + printf("Handles: %i\n", vot_handleCount()); + vot_closeVOTABLE(vot3); + printf("Handles: %i\n", vot_handleCount()); + vot_writeVOTable(vot3, "stdout", 1); + + printf("------------\\Test 5-------------------------------------------\n"); + return (0); +} + +int +pseudocode6(void) +{ + + printf("--------------Test 6-------------------------------------------\n"); + printf("------------\\Test 6-------------------------------------------\n"); + return (0); +} + +void +copy_test(char *fname) +{ + handle_t vot, copy; + + printf("--------------Copy Test-------------------------------------------\n"); + vot = vot_openVOTABLE(fname); + + /* + vot_writeVOTable(vot, "stdout", 1); + */ + + printf("Handles: %i\n", vot_handleCount()); + + + copy = vot_copyElement(vot, 0); + + + /* + vot_writeVOTable(copy, "stdout", 1); + */ + + printf("Handles: %i\n", vot_handleCount()); + + vot_closeVOTABLE(copy); + + printf("Handles: %i\n", vot_handleCount()); + + + + vot_closeVOTABLE(vot); + + printf("Handles: %i\n", vot_handleCount()); + + printf("------------\\Copy Test-------------------------------------------\n"); + +} + + + +int +main(int argc, char **argv) +{ + char *fname = "zztest.xml"; + char *fname2 = "zzdummy.xml"; + + + printf("Hello World!\n"); + + + /* + */ + pseudocode1(fname); + pseudocode2(fname); + pseudocode3(fname); + pseudocode4(); + + pseudocode5(fname, fname2); + pseudocode5_copy(fname, fname2); + + pseudocode6(); + + copy_test(fname); + + + return (0); +} diff --git a/vendor/voclient/voapps/zzwcs.c b/vendor/voclient/voapps/zzwcs.c new file mode 100644 index 00000000..e681db51 --- /dev/null +++ b/vendor/voclient/voapps/zzwcs.c @@ -0,0 +1,106 @@ +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include "fitsio.h" + + +int voc_imgQParams (char *name, double *ra, double *dec, double *rad); + + +int main (int argc, char *argv[]) +{ + double ra, dec, rad; + int status = 0; + + status = voc_imgQParams (argv[1], &ra, &dec, &rad); + printf ("RA=%f DEC=%f SZ=%f\n", ra, dec, rad); +} + + +int voc_imgQParams (char *name, double *ra, double *dec, double *rad) +{ + fitsfile *fptr; + + double xpos=0.0, ypos=0.0, xpix=0.0, ypix=0.0; + double xrval=0.0, yrval=0.0, xrpix=0.0, yrpix=0.0; + double xinc=0.0, yinc=0.0, rot=0.0; + double ll_x=0.0, ll_y=0.0, ur_x=0.0, ur_y=0.0, c_x=0.0, c_y=0.0; + long naxes[3], pcount, gcount; + int status=0, extend, simple, naxis, bitpix; + char ctype[5]; + + + /* Open the FITS file. + */ + if (ffopen (&fptr, name, READWRITE, &status) > 0) { + fprintf (stderr, "Error: open status = %d\n", status); + exit (0); + } + + /* Get the primary header keywords. + */ + ffghpr (fptr, 99, &simple, &bitpix, &naxis, naxes, &pcount, + &gcount, &extend, &status); + +fprintf (stderr, "gcount = %d pcount = %d extend = %d \n", gcount, pcount, extend); + + /* Get the header WCS keywords. + */ + ffgics (fptr, &xrval, &yrval, &xrpix, + &yrpix, &xinc, &yinc, &rot, ctype, &status); + if (status != 506) + fprintf (stderr, "Read WCS keywords with ffgics status = %d\n",status); + + + xpix = 0.5; + ypix = 0.5; + status = 0; + if (ffwldp (xpix, ypix, xrval, yrval, xrpix, yrpix, xinc, yinc, rot, ctype, + &ll_x, &ll_y, &status) > 0) { + fprintf (stderr, "Calculated sky coordinate with ffwldp status = %d\n", + status); + + } else { + status = 0; + xpix = (double) naxes[0]; + ypix = (double) naxes[1]; + ffwldp (xpix, ypix, xrval, yrval, xrpix, yrpix, xinc, yinc, rot, ctype, + &ur_x, &ur_y, &status); + + status = 0; + xpix = (double) naxes[0] / 2.; + ypix = (double) naxes[1] / 2.; + ffwldp (xpix, ypix, xrval, yrval, xrpix, yrpix, xinc, yinc, rot, ctype, + &c_x, &c_y, &status); + } + + *ra = c_x; + *dec = c_y; + *rad = sqrt ((c_x - ll_x)*(c_x - ll_x) + (c_y - ll_y)*(c_y - ll_y)); + +#ifdef DBG_WCS + printf (" CRVAL1, CRVAL2 = %16.12f, %16.12f\n", xrval, yrval); + printf (" CRPIX1, CRPIX2 = %16.12f, %16.12f\n", xrpix, yrpix); + printf (" CDELT1, CDELT2 = %16.12f, %16.12f\n", xinc, yinc); + printf (" Rotation = %10.3f, CTYPE = %s\n", rot, ctype); + printf (" Pixels (%8.4f,%8.4f) --> (%11.6f, %11.6f) Sky\n", + xpix, ypix, ll_x, ll_y); + + fprintf (stderr, "RA=%f DEC=%f SZ=%f\n", c_x, c_y, + sqrt ((c_x - ll_x)*(c_x - ll_x) + (c_y - ll_y)*(c_y - ll_y))); + + ffxypx (xpos, ypos, xrval, yrval, xrpix, yrpix, xinc, yinc, rot, ctype, + &xpix, &ypix, &status); + printf ("Calculated pixel coordinate with ffxypx status = %d\n", status); + printf (" Sky (%11.6f, %11.6f) --> (%8.4f,%8.4f) Pixels\n", + xpos, ypos, xpix, ypix); +#endif + + + if (ffclos (fptr, &status) > 0) { + fprintf (stderr, "Error: close status = %d\n", status); + return (-1); + } + + return (0); +} |