aboutsummaryrefslogtreecommitdiff
path: root/vendor/voclient/libvoclient/vocLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/voclient/libvoclient/vocLib.c')
-rw-r--r--vendor/voclient/libvoclient/vocLib.c920
1 files changed, 920 insertions, 0 deletions
diff --git a/vendor/voclient/libvoclient/vocLib.c b/vendor/voclient/libvoclient/vocLib.c
new file mode 100644
index 00000000..19b2a435
--- /dev/null
+++ b/vendor/voclient/libvoclient/vocLib.c
@@ -0,0 +1,920 @@
+/***************************************************************************
+ *
+ * VOCLient Library -- Client interface library to the VOClient daemon
+ * application. This API allows non-Java programs to make use of the DAL
+ * client interface by means of a remote procedure call between this
+ * interface and the VOClient daemon. State is maintained in the server and
+ * values passed back are language-neutral integer 'handles' on the remote
+ * objects, or simple int/double/string values.
+ *
+ * All tasks must initialize the VO Client and establish a connection to
+ * the VOClient daemon by calling voc_initVOClient() before making any service
+ * connections, thereafter new connections may be opened/closed at will.
+ * Convenience procedures allow for easy use of specific services, e.g. Cone
+ * or Siap. Service-specific parameters may be added to a query using the
+ * voc_add<type>Param() calls. No action is taken until an execute of the
+ * query is performed, applications may get back a handle on the result and
+ * interrogate attributes directly, the raw VOTable or a CSV representation
+ * of the result may also be returned.
+ *
+ * High-Level Functions:
+ * ---------------------
+ *
+ * voc_initVOClient (config_opts)
+ * voc_closeVOClient (shutdown_flag)
+ * voc_abortVOClient (errcode, errmsg)
+ *
+ * string = voc_coneCaller (url, ra, dec, sr, otype)
+ * status = voc_coneCallerToFile (url, ra, dec, sr, otype, file)
+ * string = voc_siapCaller (url, ra, dec, rsize, dsize, fmt, otype)
+ * status = voc_siapCallerToFile (url, ra, dec, rsize, dsize, fmt, otype, file)
+ *
+ *
+ * Interface Utility Procedures:
+ * ------------------------------
+ *
+ * flag = voc_validateObj (hcode)
+ * voc_debugLevel (level)
+ * voc_freePointer (ptr)
+ *
+ *
+ * Main DAL Interface Procedures:
+ * ------------------------------
+ *
+ * dal = voc_openConnection (svc_url, type)
+ * dal = voc_openConeConnection (svc_url) # Utility aliases
+ * dal = voc_openSiapConnection (svc_url)
+ * voc_closeConnection (dal)
+ *
+ * count = voc_getServiceCount (dal)
+ * voc_addServiceURL (dal, svc_url)
+ * url = voc_getServiceURL (dal, index)
+ *
+ * query = voc_getQuery (dal, type)
+ * query = voc_getConeQuery (dal, ra, dec, sr)
+ * query = voc_getSiapQuery (dal, ra, dec, ra_size, dec_size, format)
+ *
+ * stat = voc_addIntParam (query, pname, ival)
+ * stat = voc_addFloatParam (query, pname, dval)
+ * stat = voc_addStringParam (query, pname, str)
+ *
+ * url_str = voc_getQueryString (query, type, index)
+ *
+ * qr = voc_executeQuery (query)
+ * stat = voc_executeQueryAs (query, fname, type)
+ * csv_str = voc_executeCSV (query)
+ * vot_str = voc_executeVOTable (query)
+ *
+ * count = voc_getRecordCount (qr)
+ * rec = voc_getRecord (qr, recnum)
+ *
+ * attr = voc_getAttribute (rec, char *attrname)
+ * count = voc_getAttrCount (rec)
+ * list_str = voc_getAttrList (rec)
+ *
+ * ival = voc_intValue (attr)
+ * dval = voc_floatValue (attr)
+ * str = voc_stringValue (attr)
+ *
+ * voc_setIntAttr (rec, attrname, ival) (Not Yet Implemented)
+ * voc_setFloatAttr (rec, attrname, dval) ( " " " )
+ * voc_setStringAttr (rec, attrname, str) ( " " " )
+ *
+ * stat = voc_getDataset (rec, acref, fname)
+ *
+ *
+ * Sesame Name Resolver Interface:
+ * -------------------------------
+ *
+ * sr = voc_nameResolver (target)
+ * pos_str = voc_resolverPos (sr)
+ * radeg = voc_resolverRA (sr)
+ * decdeg = voc_resolverDEC (sr)
+ *
+ *
+ * Client programs may be written in any language that can interface to
+ * C code. Sample programs using the interface are provided as is a SWIG
+ * interface definition file. This inferface is based closely on the DAL
+ * client code produced for the 2005 NVOSS, as that interface evolves
+ *
+ *
+ * Michael Fitzpatrick, NOAO, June 2006
+ *
+ **************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+
+#define _VOCLIENT_LIB_
+#include "VOClient.h"
+
+
+VOClient *vo = (VOClient *) NULL; /* Interface runtime struct */
+
+#define SVR_MAXTRY 5
+#define DEF_VOCSERVER_PORT 6200
+
+
+typedef struct {
+ char server[SZ_FNAME]; /* VOClient server daemon */
+ char proxy[SZ_FNAME]; /* VOClient server proxy */
+ char config[SZ_FNAME]; /* VOClient config file */
+ char path[SZ_FNAME]; /* VOClientd path */
+ char runid[SZ_FNAME]; /* RUNID logging string */
+
+ int port; /* Server port */
+ int spawn; /* spawn a local daemon? */
+ int console; /* initiate a console? */
+ int onetrip; /* force a single instance? */
+ int use_cache; /* use object/registry cache? */
+ int use_runid; /* use RUNID parameter? */
+ int quiet; /* suppress API output? */
+} vocOpt;
+
+
+
+
+/*************************************
+ * Private procedure declarations.
+ *************************************/
+static int voc_openVOCServer (char *dev);
+static int voc_parseDev (char *dev, unsigned short *host_port,
+ unsigned long *host_addr);
+
+static vocOpt *voc_initOpts ();
+static vocOpt *voc_parseOpts (char *opts);
+static vocOpt *voc_readConfig (char *config);
+
+static char *voc_cacheCreate (char *home, char *cache, char *subdir);
+
+vocOpt *vopt = (vocOpt *) NULL;
+
+
+void voc_exitHandler();
+
+
+/******************************************************************************
+** OPENVOCLIENT -- Open and initialize the VOClient interface.
+*/
+int
+voc_initVOClient (char *opts)
+{
+ register int i;
+ char *home, *s, config[128], *opt_str;
+
+ char *VOCServer = (char *)NULL;
+ char *VOCProxy = (char *)NULL;
+ int port = DEF_VOCSERVER_PORT;
+ int spawn = TRUE;
+ int console = FALSE;
+ int onetrip = FALSE;
+
+
+ /* Initialize the options.
+ */
+ vopt = (vocOpt *) voc_initOpts ();
+
+
+ /* Configuration order (should be):
+ **
+ ** - defaults (default)
+ ** - $home/.voclient/config file (user pref default)
+ ** - application settings (app requirements)
+ ** - environment settings (app-specific req.)
+ */
+
+ /* Get a debug flag from the opt string or the environment if we can.
+ */
+ opt_str = ( opts ? opts : getenv ("VOC_OPTS"));
+ if (opt_str) {
+ if (! (vopt = voc_parseOpts (opt_str))) {
+ if (!vopt->quiet)
+ fprintf (stderr, "ERROR: Invalid opt string '%s'!\n", opt_str);
+ return ERR;
+
+ } else {
+ /* Allow an opt string to specify a config file to be used.
+ */
+ if (vopt->config && access (vopt->config, R_OK) == 0)
+ vopt = voc_readConfig (vopt->config);
+ }
+
+ } else {
+ /* Attempt to open the config file. This may be specified using
+ ** either and environment variable or the default path.
+ */
+ memset (config, 0, 128);
+ if ((s = getenv ("VOC_CONFIG")))
+ strcpy (config, s);
+ else if ((home = getenv ("HOME")))
+ sprintf (config, "%s/.voclient/config", home);
+
+ /* Use the config from the environment, then try the user's
+ ** config file before using the default.
+ */
+ if (access (config, R_OK) == 0)
+ vopt = voc_readConfig (config);
+ }
+
+
+ /* Use defaults if we didn't get any config options.
+ */
+ if (vopt == (vocOpt *)NULL) {
+ vopt = (vocOpt *) calloc (1, sizeof (vocOpt));
+ strcpy (vopt->server, DEF_SERVER);
+ strcpy (vopt->proxy, DEF_NET_SERVER);
+ strcpy (vopt->runid, DEF_RUNID);
+ vopt->port = DEF_VOCSERVER_PORT;
+ vopt->spawn = TRUE;
+ vopt->quiet = TRUE;
+ vopt->use_cache = TRUE;
+ vopt->use_runid = TRUE;
+ vopt->console = FALSE;
+ vopt->onetrip = onetrip;
+ }
+
+
+ /* Allow an environment variable to override a config file setting or
+ ** task option string.
+ */
+ VOCServer = ((s = getenv("VOC_SERVER")) ? s : vopt->server);
+ VOCProxy = ((s = getenv("VOC_PROXY")) ? s : vopt->proxy);
+
+ if (0) {
+ fprintf (stderr, "Server: '%s' Proxy: '%s' ", VOCServer, VOCProxy);
+ fprintf (stderr, "spawn=%d console=%d port=%d onetrip=%d\n",
+ spawn, console, port, onetrip);
+ }
+
+ if (vo) {
+ if (VOC_DEBUG)
+ fprintf (stderr, "Warning: VOClient already initialized!\n");
+ return OK;
+
+ } else {
+ /* Allocate the struct.
+ */
+ vo = calloc (1, sizeof (VOClient));
+
+ /* Get a channel to a server. If we can't start our own daemon, try
+ ** connecting to the proxy server.
+ */
+ if (!vopt->spawn) {
+ if ((vo->io_chan = voc_openVOCServer(VOCProxy)) == (int) VOC_NULL) {
+ if (!vopt->quiet)
+ fprintf (stderr,
+ "Cannot connect to local or proxy server.\n");
+ return ERR;
+ }
+
+
+ } else if ((vo->io_chan=voc_openVOCServer(VOCServer))==(int)VOC_NULL) {
+ char *cmd = calloc (1, 128);
+
+ if (VOC_DEBUG)
+ fprintf (stderr, "Couldn't open server, starting private...\n");
+
+ /* FIXME --
+ //system ("voclientd -private >& /dev/null &");
+ if (opts && strstr (opts, "console")) {
+ system ("voclientd -gui &");
+ } else {
+ system ("voclientd >& /dev/null &");
+ }
+ */
+ if (vopt->console)
+ sprintf (cmd, "%s -gui -port %d &",
+ (vopt->path[0] ? vopt->path : "voclientd"), vopt->port);
+ else
+ sprintf (cmd, "%s -port %d > /dev/null 2>&1 &",
+ (vopt->path[0] ? vopt->path : "voclientd"), vopt->port);
+
+ system (cmd);
+
+ /* We couldn't connect to the default server, so try to start
+ * a private version for this session. Timeout after SVR_MAXTRY
+ * attempts.
+ */
+ for (i=SVR_MAXTRY; i && vo->io_chan == (int) VOC_NULL; i--) {
+ sleep (1);
+ vo->io_chan = voc_openVOCServer ("6200");
+ }
+ if (i == 0) {
+ if ((vo->io_chan=voc_openVOCServer(VOCProxy))==(int)VOC_NULL) {
+ if (!vopt->quiet)
+ fprintf (stderr,
+ "ERROR: Cannot connect to or create server process\n");
+ return ERR;
+ }
+ }
+ }
+ }
+
+ /* Get a debug flag from the environment if we can.
+ */
+ vo->debug = ((s = getenv("VOC_DEBUG")) != NULL);
+ if (s && (i = atoi(s)))
+ vo->debug = i;
+
+ vo->quiet = vopt->quiet;
+ vo->use_cache = vopt->use_cache;
+ vo->use_runid = vopt->use_runid;
+ vo->onetrip = vopt->onetrip;
+ vo->runid = vopt->runid;
+
+ /* Post an exit handler so we clean up properly.
+ */
+ (void) atexit (voc_exitHandler);
+
+ return OK;
+}
+
+
+/******************************************************************************
+** CLOSEVOCLIENT -- Close and free the VOClient interface.
+*/
+void
+voc_closeVOClient (int shutdown)
+{
+ vocMsg_t *msg = (vocMsg_t *) msg_quitMsg ();
+
+
+ if (vo == (VOClient *) NULL) /* no-op on null pointer */
+ return;
+
+ if (vo->onetrip || shutdown) {
+ vocMsg_t *msg = (vocMsg_t *) msg_shutdownMsg ();
+
+ /* Send the shutdown request. We don't expect a reply so send a
+ * raw message and assume it got there. Use an asynchrnous write
+ * so we don't block.
+ */
+ (void) msg_sendRawMsg (vo->io_chan, msg);
+
+ } else {
+ vocRes_t *result;
+
+ /* Send the quit request. */
+ if (msg_resultStatus ((result = msg_sendMsg (vo->io_chan, msg))) == ERR)
+ if (vo->debug)
+ fprintf (stderr, "ERROR quitting voclientd.\n");
+
+ free ((vocRes_t *) result);
+ }
+
+ /* Close the VOClient connection.
+ */
+ if (vo->io_chan >= 0) {
+ close (vo->io_chan);
+ vo->io_chan = -1;
+ }
+
+ /* Free the structure.
+ */
+ if (msg) free ((vocMsg_t *) msg);
+ if (vo) free ((void *) vo);
+ vo = (VOClient *) NULL;
+}
+
+
+
+/******************************************************************************
+** ABORTVOCLIENT -- Close the VOClient interface and abort the application.
+*/
+void
+voc_abortVOClient (int code, char *msg)
+{
+ if (msg && !vo->quiet)
+ fprintf (stderr, "ABORT: %s\n", msg);
+ voc_closeVOClient (1);
+ exit (code);
+}
+
+
+
+/******************************************************************************
+** EXITHANDLER -- Automatically disconnect clients that forget to do so.
+*/
+void
+voc_exitHandler()
+{
+ if (vo)
+ voc_closeVOClient (0);
+}
+
+
+/******************************************************************************
+** VALIDATEOBJECT -- Given the hashcode hand for an object, verify it is
+** still valid in the daemon hasmap. Returns 0 if not valid, 1 if valid.
+*/
+int
+voc_validateObject (int hcode)
+{
+ vocRes_t *result = (vocRes_t *) NULL;
+ vocMsg_t *msg = (vocMsg_t *) msg_newCallMsg (hcode, "validateObject", 0);
+ int flag = 0;
+
+ /* Send message and read result. */
+ if (msg_resultStatus ((result = msg_sendMsg (vo->io_chan, msg))) != ERR)
+ flag = msg_getIntResult (result, 0);
+
+ if (msg) free ((void *)msg); /* free the pointers */
+ if (result) free ((void *)result);
+
+ return (flag);
+}
+
+
+/******************************************************************************
+** VOCREADY -- Verify that the VO Client daemon is alive and well.
+*/
+int
+voc_ready ()
+{
+ vocRes_t *result = (vocRes_t *) NULL;
+ vocMsg_t *msg = (vocMsg_t *) msg_ackMsg ();
+ int flag = 0;
+
+ /* Send message and read result. */
+ if (msg_resultStatus ((result = msg_sendMsg (vo->io_chan, msg))) != ERR)
+ flag = msg_getIntResult (result, 0);
+
+ if (msg) free ((void *)msg); /* free the pointers */
+ if (result) free ((void *)result);
+
+ return (flag);
+}
+
+
+
+/******************************************************************************
+** FREEPOINTER -- Free a pointer allocated in the interface. For Client
+** apps like the IRAF CL a pointer returned for a string cannot be freed
+** properly because of a proprietary memory i/o interface. So, we'll pass
+** it back into the interface to free it.
+*/
+void
+voc_freePointer (char *ptr)
+{
+ if (ptr)
+ free ((void *) ptr);
+}
+
+
+/******************************************************************************
+** DEBUGLEVEL -- Set the package debugging output level.
+*/
+void
+voc_debugLevel (int level) { vo->debug = level; }
+
+
+
+
+
+
+/*****************************************************************************
+ *****************************************************************************
+ ***
+ *** PRIVATE PROCEDURES
+ ***
+ *****************************************************************************
+ ****************************************************************************/
+
+
+/******************************************************************************
+** VOC_OPENVOCSERVER -- Open a connection to the VOClient server. The caller
+** may either specify a connection at device open time, or the procedure will
+** attempt to connect on a unix socket or local port if that fails.
+** The syntax for the imtdev argument is as follows:
+**
+** <domain> : <address>
+**
+** where <domain> is one of "inet" (internet tcp/ip socket), "unix" (unix
+** domain socket) or "fifo" (named pipe). The form of the address depends
+** upon the domain, as illustrated in the examples below.
+**
+** inet:6200 (or '6200') Server connection to port 6200 on the local
+** host. For a client, a connection to the
+** given port on the local host.
+**
+** inet:6200:foo.bar.edu Client connection to port 6200 on internet
+** host foo.bar.edu. The dotted form of address
+** may also be used.
+*/
+
+static int voc_openVOCServer (char *dev)
+{
+ int fd;
+ unsigned short host_port;
+ unsigned long host_addr;
+ struct sockaddr_in sockaddr;
+
+
+ if (dev == (char *) NULL)
+ dev = DEF_SERVER;
+
+ if (voc_parseDev (dev, &host_port, &host_addr) == ERR) {
+ if (!vo->quiet)
+ fprintf (stderr, "Cannot parse device: '%s'.\n", dev);
+ return ((int ) VOC_NULL);
+
+ } else {
+ /* Get a socket.
+ */
+ if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
+ if (!vo->quiet)
+ fprintf (stderr, "Cannot create inet socket on '%s'.\n", dev);
+ return ((int ) VOC_NULL);
+ }
+
+ /* Compose a network address.
+ */
+ memset ((char *)&sockaddr, 0, sizeof(sockaddr));
+ sockaddr.sin_family = AF_INET;
+ sockaddr.sin_port = host_port; /* htons() done above */
+ bcopy ((char *)&host_addr,(char *)&sockaddr.sin_addr,sizeof(host_addr));
+
+ /* Connect to the server.
+ */
+ if (connect(fd,(struct sockaddr *)&sockaddr,sizeof(sockaddr)) < 0) {
+ close (fd);
+ /*
+ if (!vo->quiet)
+ fprintf (stderr, "Cannot open server connection on '%s'.\n",
+ dev);
+ */
+ return ((int ) VOC_NULL);
+ }
+ }
+ if (VOC_DEBUG) fprintf (stderr, "Connection established on '%s'\n", dev);
+
+ return (fd);
+}
+
+
+
+/******************************************************************************
+** VOC_PARSEDEV -- Parse the VOClient Server device string to extract the host
+** and port number information.
+*/
+
+static int
+voc_parseDev (char *dev, unsigned short *hport, unsigned long *host_addr)
+{
+ char *ip, osfn[128], buf[128], host_str[128];
+ unsigned short port;
+ register int i;
+ struct hostent *hp;
+
+
+ if (dev == NULL)
+ return ERR;
+
+ memset (osfn, 0, 128);
+ memset (host_str, 0, 128);
+
+ /* Expand any %d fields in the network address to the UID. */
+ sprintf (osfn, (char *)dev, getuid(), getuid());
+
+ /* Form is a port number with an optional node name. First extract
+ * the port number.
+ */
+ if (isdigit (osfn[0]))
+ ip = osfn;
+ else if (strncmp (osfn, "inet:", 5) == 0)
+ ip = osfn + 5;
+
+ /* Get the port number. */
+ for (i=0; isdigit (*ip); i++, ip++)
+ buf[i] = (char) *ip;
+
+ port = atoi (buf); /* set port number */
+ *hport = htons (port);
+
+ /* Get host address. This may be specified either has a host
+ * name or as an Internet address in dot notation. If no host
+ * name is specified default to the local host.
+ */
+ if (*ip++ == ':') {
+ strcpy (host_str, ip);
+ } else
+ sprintf (host_str, "%s", "127.0.0.1");
+
+ if (isdigit (host_str[0])) {
+ *host_addr = inet_addr (host_str);
+ if ((int)*host_addr == -1)
+ return ERR;
+
+ } else if ((hp = gethostbyname (host_str))) {
+ bcopy (hp->h_addr, (char *)host_addr, sizeof(*host_addr));
+
+ } else
+ return ERR;
+
+ if (VOC_DEBUG)
+ fprintf (stderr, "parseDev: '%s' --> port=%d node='%s'\n",
+ dev, port, host_str);
+
+ return OK;
+}
+
+
+/******************************************************************************
+** VOC_INITOPTS -- Initialize the VOClient configuration options.
+*/
+static vocOpt *
+voc_initOpts ()
+{
+ /* Use defaults if we didn't get any config options.
+ */
+ if (vopt == (vocOpt *)NULL)
+ vopt = (vocOpt *) calloc (1, sizeof (vocOpt));
+
+ strcpy (vopt->server, DEF_SERVER);
+ strcpy (vopt->proxy, DEF_NET_SERVER);
+ strcpy (vopt->runid, DEF_RUNID);
+ vopt->port = DEF_VOCSERVER_PORT;
+ vopt->spawn = TRUE;
+ vopt->quiet = TRUE;
+ vopt->use_cache = TRUE;
+ vopt->use_runid = TRUE;
+ vopt->console = FALSE;
+ vopt->onetrip = FALSE;
+
+ return (vopt);
+}
+
+
+
+/******************************************************************************
+** VOC_PARSEOPTS -- Parse the VOClient Server option string. Options are
+** encoded as a comma-delimited list of options that include:
+**
+** spawn If set, will attempt to spawn a local instance of the
+** voclient daemon if not already running.
+**
+** port Default port to use for a local voclient daemon.
+**
+** console Create a GUI console window for the local daemon?
+**
+** quiet Client API shouldn't produce any error output, it
+** will be handled by the application.
+**
+** runid Set the RUNID logging string
+**
+** use_cache Use the object/registry cache?
+**
+** use_runid Use the RUNID parameter?
+**
+** server VOClient daemon server address. The address is of
+** the form
+** <port> ':' <host>
+**
+** where <host> can be a local machine name, a fully-
+** qualified domain name, or an IP address. <port> is
+** the socket number on which the 'voclientd' is running
+** on that machine. A server will be started if the
+** 'use_local' flag is set and <host> is 'localhost' or
+** the current machine name, the <port> specified here
+** will override the 'port' setting
+**
+** Keyword names may be abbreviated to the smallest unique word.
+**
+** An example opt string would be
+**
+** server=8081:localhost,spawn=yes,console=yes,runid=test
+**
+** to spawn a voclientd running on the local machine at port 8081 with a
+** GUI console panel.
+*/
+
+#define SZ_OPT_BUF 64
+
+
+static vocOpt *
+voc_parseOpts (char *opts)
+{
+ register int i;
+ char *ip, keyw[SZ_OPT_BUF], val[SZ_OPT_BUF];
+ char lserver[SZ_OPT_BUF];
+ char lproxy[SZ_OPT_BUF];
+ char lconfig[SZ_OPT_BUF];
+ char lpath[SZ_OPT_BUF];
+ char lrunid[SZ_OPT_BUF];
+ int lport = DEF_VOCSERVER_PORT;
+ int lspawn = TRUE;
+ int lcons = FALSE;
+ int lone = FALSE;
+ int lquiet = TRUE;
+ int luse_cache = TRUE;
+ int luse_runid = TRUE;
+ int len;
+
+ vocOpt *vopt = (vocOpt *) NULL;
+
+
+ memset (lserver, 0, SZ_OPT_BUF); strcpy (lserver, DEF_SERVER);
+ memset (lproxy, 0, SZ_OPT_BUF); strcpy (lproxy, DEF_NET_SERVER);
+ memset (lconfig, 0, SZ_OPT_BUF);
+ memset (lpath, 0, SZ_OPT_BUF);
+
+ /* Loop through the option string, setting values.
+ */
+ ip = opts;
+ while (*ip) {
+ memset (keyw, 0, SZ_OPT_BUF);
+ memset (val, 0, SZ_OPT_BUF);
+
+ for (i=0; *ip && *ip != '=' && i < SZ_OPT_BUF; )
+ keyw[i++] = tolower (*ip++);
+
+ if (*ip != '=') {
+ /* The presence of a keyword implies it's turned on.
+ */
+ val[0] = '1';
+ } else {
+ ip++;
+ for (i=0; *ip && *ip != ',' && i < SZ_OPT_BUF; )
+ val[i++] = tolower (*ip++);
+ }
+ len = strlen (val);
+
+
+ /* Ugly but effective parsing.
+ */
+ if (strncmp ("config", keyw, 4) == 0)
+ strcpy (lconfig, val);
+
+ else if (strncmp ("console", keyw, 4) == 0)
+ lcons = (val[0] == 'y' || val[0] == '1');
+
+ else if (strncmp ("onetrip", keyw, 2) == 0)
+ lone = (val[0] == 'y' || val[0] == '1');
+
+ else if (strncmp ("port", keyw, 2) == 0)
+ lport = atoi (val);
+
+ else if (strncmp ("proxy", keyw, 2) == 0)
+ strcpy (lproxy, val);
+
+ else if (strncmp ("runid", keyw, 3) == 0)
+ strcpy (lrunid, val);
+
+ /*
+ else if (strncmp ("voc_path", keyw, 8) == 0)
+ strcpy (lpath, val);
+ if (val[len-1] != '/')
+ strcat (lpath, "/");
+ */
+
+ else if (strncmp ("spawn", keyw, 2) == 0)
+ lspawn = (val[0] == 'y' || val[0] == '1');
+
+ else if (strncmp ("use_cache", keyw, 5) == 0)
+ luse_cache = (val[0] == 'y' || val[0] == '1');
+
+ else if (strncmp ("use_runid", keyw, 5) == 0)
+ luse_runid = (val[0] == 'y' || val[0] == '1');
+
+ else if (strncmp ("server", keyw, 2) == 0)
+ strcpy (lserver, val);
+
+ else if (strncmp ("quiet", keyw, 2) == 0)
+ lquiet = atoi (val);
+
+ else if (!lquiet)
+ fprintf (stderr, "parseOpt: invalid option '%s'='%s'\n", keyw, val);
+
+ /* Skip to next option or break.
+ */
+ if (*ip && *ip == ',')
+ ip++;
+ }
+
+
+ /* Save the values and return.
+ */
+ vopt = calloc (1, sizeof (vocOpt));
+ strcpy (vopt->server, lserver);
+ strcpy (vopt->proxy, lproxy);
+ strcpy (vopt->config, lconfig);
+ strcpy (vopt->path, lpath);
+ strcpy (vopt->runid, lrunid);
+ vopt->onetrip = lone;
+ vopt->port = lport;
+ vopt->spawn = lspawn;
+ vopt->quiet = lquiet;
+ vopt->use_cache = luse_cache;
+ vopt->use_runid = luse_runid;
+ vopt->console = lcons;
+
+ return (vopt);
+}
+
+
+static vocOpt *
+voc_readConfig (char *config)
+{
+ return ((vocOpt *)NULL);
+}
+
+
+
+/******************************************************************************
+** Cache Utility procedures.
+*/
+
+char *
+voc_getCacheDir (char *subdir)
+{
+ char *home, cache[SZ_FNAME], fullpath[SZ_FNAME], *path;
+ DIR *dir;
+
+
+ if ((home = getenv ("HOME")) ) {
+ memset (cache, 0, SZ_FNAME);
+ sprintf (cache, "%s/.voclient/cache", home);
+ sprintf (fullpath, "%s/%s", cache, subdir);
+ } else
+ return ((char *) NULL);
+
+
+ /* Create the cache dir if it doesn't already exist.
+ */
+ if (!(dir = opendir (fullpath)) )
+ path = voc_cacheCreate (home, cache, subdir);
+ else {
+ closedir (dir);
+ path = calloc (1, strlen (fullpath)+2);
+ strcpy (path, fullpath);
+ }
+
+ if ((dir = opendir (path)) ) {
+ closedir (dir);
+ return (path);
+ } else
+ return ((char *)NULL);
+}
+
+
+/* Create any needed cache directories.
+*/
+static char *
+voc_cacheCreate (char *home, char *cache, char *subdir)
+{
+ char *path, fname[SZ_FNAME];
+ DIR *dir;
+
+
+ /* Be sure we can open the HOME dir. */
+ if ((dir = opendir (home)) ) {
+ closedir (dir);
+ sprintf (fname, "%s/.voclient/", home);
+
+ /* Check for access to the $HOME/.voclient dir, if it doesn't exist
+ ** then create it.
+ */
+ if (!(dir = opendir (fname)) ) {
+ mkdir (fname, (mode_t) 0777);
+ sprintf (fname, "%s/.voclient/cache", home);
+ mkdir (fname, (mode_t) 0777); /* create cache dir */
+
+ } else {
+ /* The $HOME/.voclient exists, now check for a cache dir.
+ */
+ sprintf (fname, "%s/.voclient/cache", home);
+ if (!(dir = opendir (fname)) )
+ mkdir (fname, (mode_t) 0777);
+ }
+ if (dir)
+ closedir (dir);
+
+ /* We now have the cache dir, see what's to be done about a subdir.
+ */
+ if (subdir) {
+ path = calloc (1, SZ_FNAME);
+
+ sprintf (path, "%s/%s", cache, subdir);
+ if (!(dir = opendir (path)) )
+ mkdir (path, (mode_t) 0777);
+ else
+ closedir (dir);
+ return (path);
+
+ } else
+ return (strdup (cache));
+
+ }
+
+ return ((char *) NULL);
+}
+
+
+int voc_dbg (void) { static int count = 0; count++; return (count); }