mirror of
https://github.com/Unidata/netcdf-c.git
synced 2025-02-11 16:40:36 +08:00
2. modify oc2/ocrc.c rcfilenames to look for .ocrc before .dodsrc. 3. Modify testauth.sh to avoid using names that might already exist for cookies file and netrc file. Still must use .ocrc to test for local/home search. 4. Modify testauth.sh to save and restore any file it creates that already exists.
742 lines
22 KiB
C
742 lines
22 KiB
C
/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
|
|
See the COPYRIGHT file for more information. */
|
|
|
|
#include "config.h"
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "ocinternal.h"
|
|
#include "ocdebug.h"
|
|
#include "oclog.h"
|
|
|
|
#define RTAG ']'
|
|
#define LTAG '['
|
|
|
|
#define TRIMCHARS " \t\r\n"
|
|
|
|
static OCerror rc_search(const char* prefix, const char* rcfile, char** pathp);
|
|
|
|
static int rcreadline(FILE* f, char* more, int morelen);
|
|
static void rctrim(char* text);
|
|
static char* combinecredentials(const char* user, const char* pwd);
|
|
|
|
static void storedump(char* msg, struct OCTriple*, int ntriples);
|
|
|
|
/* Define default rc files and aliases, also defines search order*/
|
|
static char* rcfilenames[] = {".ocrc",".dodsrc",NULL};
|
|
|
|
/* The Username and password are in the URL if the URL is of the form:
|
|
* http://<name>:<passwd>@<host>/....
|
|
*/
|
|
static int
|
|
occredentials_in_url(const char *url)
|
|
{
|
|
char *pos = strstr(url, "http://");
|
|
if (!pos)
|
|
return 0;
|
|
pos += 7;
|
|
if (strchr(pos, '@') && strchr(pos, ':'))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
static OCerror
|
|
ocextract_credentials(const char *url, char **userpwd, char **result_url)
|
|
{
|
|
OCURI* parsed = NULL;
|
|
if(!ocuriparse(url,&parsed))
|
|
return OCTHROW(OC_EBADURL);
|
|
if(parsed->userpwd == NULL) {
|
|
ocurifree(parsed);
|
|
return OCTHROW(OC_EBADURL);
|
|
}
|
|
if(userpwd) *userpwd = strdup(parsed->userpwd);
|
|
ocurifree(parsed);
|
|
return OC_NOERR;
|
|
}
|
|
|
|
char*
|
|
occombinehostport(const OCURI* uri)
|
|
{
|
|
char* hp;
|
|
int len = 0;
|
|
|
|
if(uri->host == NULL)
|
|
return NULL;
|
|
else
|
|
len += strlen(uri->host);
|
|
if(uri->port != NULL)
|
|
len += strlen(uri->port);
|
|
hp = (char*)malloc(len+1);
|
|
if(hp == NULL)
|
|
return NULL;
|
|
if(uri->port == NULL)
|
|
occopycat(hp,len+1,1,uri->host);
|
|
else
|
|
occopycat(hp,len+1,3,uri->host,":",uri->port);
|
|
return hp;
|
|
}
|
|
|
|
static char*
|
|
combinecredentials(const char* user, const char* pwd)
|
|
{
|
|
int userPassSize;
|
|
char *userPassword;
|
|
|
|
if(user == NULL) user = "";
|
|
if(pwd == NULL) pwd = "";
|
|
|
|
userPassSize = strlen(user) + strlen(pwd) + 2;
|
|
userPassword = malloc(sizeof(char) * userPassSize);
|
|
if (!userPassword) {
|
|
oclog(OCLOGERR,"Out of Memory\n");
|
|
return NULL;
|
|
}
|
|
occopycat(userPassword,userPassSize-1,3,user,":",pwd);
|
|
return userPassword;
|
|
}
|
|
|
|
static int
|
|
rcreadline(FILE* f, char* more, int morelen)
|
|
{
|
|
int i = 0;
|
|
int c = getc(f);
|
|
if(c < 0) return 0;
|
|
for(;;) {
|
|
if(i < morelen) /* ignore excess characters */
|
|
more[i++]=c;
|
|
c = getc(f);
|
|
if(c < 0) break; /* eof */
|
|
if(c == '\n') break; /* eol */
|
|
}
|
|
/* null terminate more */
|
|
more[i] = '\0';
|
|
return 1;
|
|
}
|
|
|
|
/* Trim TRIMCHARS from both ends of text; */
|
|
static void
|
|
rctrim(char* text)
|
|
{
|
|
char* p = text;
|
|
size_t len = strlen(text);
|
|
int i;
|
|
/* locate first non-trimchar */
|
|
for(;*p;p++) {
|
|
if(strchr(TRIMCHARS,*p) == NULL) break; /* hit non-trim char */
|
|
}
|
|
memmove(text,p,strlen(p)+1);
|
|
len = strlen(text);
|
|
/* locate last non-trimchar */
|
|
if(len > 0) {
|
|
for(i=(len-1);i>=0;i--) {
|
|
if(strchr(TRIMCHARS,text[i]) == NULL) {
|
|
text[i+1] = '\0'; /* elide trailing trimchars */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
ocparseproxy(OCstate* state, char* v)
|
|
{
|
|
/* Do not free these; they are pointers into v; free v instead */
|
|
char *host_pos = NULL;
|
|
char *port_pos = NULL;
|
|
if(v == NULL || strlen(v) == 0)
|
|
return OC_NOERR; /* nothing there*/
|
|
if (occredentials_in_url(v)) {
|
|
char *result_url = NULL;
|
|
ocextract_credentials(v, &state->proxy.userpwd, &result_url);
|
|
v = result_url;
|
|
}
|
|
/* allocating a bit more than likely needed ... */
|
|
host_pos = strstr(v, "http://");
|
|
if (host_pos)
|
|
host_pos += strlen("http://");
|
|
else
|
|
host_pos = v;
|
|
port_pos = strchr(host_pos, ':');
|
|
if (port_pos) {
|
|
size_t host_len;
|
|
char *port_sep = port_pos;
|
|
port_pos++;
|
|
*port_sep = '\0';
|
|
host_len = strlen(host_pos);
|
|
state->proxy.host = malloc(sizeof(char) * host_len + 1);
|
|
if (state->proxy.host == NULL)
|
|
return OCTHROW(OC_ENOMEM);
|
|
strncpy(state->proxy.host, host_pos, host_len);
|
|
state->proxy.host[host_len] = '\0';
|
|
state->proxy.port = atoi(port_pos);
|
|
} else {
|
|
size_t host_len = strlen(host_pos);
|
|
state->proxy.host = malloc(sizeof(char) * host_len + 1);
|
|
if (state->proxy.host == NULL)
|
|
return OCTHROW(OC_ENOMEM);
|
|
strncpy(state->proxy.host, host_pos, host_len);
|
|
state->proxy.host[host_len] = '\0';
|
|
state->proxy.port = 80;
|
|
}
|
|
#if 0
|
|
state->proxy.host[v_len] = '\0';
|
|
state->proxy.port = atoi(v);
|
|
s_len = strlen(v);
|
|
state->proxy.user = malloc(sizeof(char) * s_len + 1);
|
|
if (state->proxy.user == NULL)
|
|
return OC_ENOMEM;
|
|
strncpy(state->proxy.user, v, s_len);
|
|
state->proxy.user[s_len] = '\0';
|
|
p_len = strlen(v);
|
|
state->proxy.password = malloc(sizeof(char) * p_len + 1);
|
|
if (state->proxy.password == NULL)
|
|
return OCTHROW(OC_ENOMEM);
|
|
strncpy(state->proxy.password, v, p_len);
|
|
state->proxy.password[p_len] = '\0';
|
|
#endif /*0*/
|
|
if (ocdebug > 1) {
|
|
oclog(OCLOGNOTE,"host name: %s", state->proxy.host);
|
|
#ifdef INSECURE
|
|
oclog(OCLOGNOTE,"user+pwd: %s", state->proxy.userpwd);
|
|
#endif
|
|
oclog(OCLOGNOTE,"port number: %d", state->proxy.port);
|
|
}
|
|
if(v) free(v);
|
|
return OC_NOERR;
|
|
}
|
|
|
|
/* insertion sort the triplestore based on url */
|
|
static void
|
|
sorttriplestore(struct OCTriplestore* store)
|
|
{
|
|
int i, nsorted;
|
|
struct OCTriple* sorted = NULL;
|
|
|
|
if(store == NULL) return; /* nothing to sort */
|
|
if(store->ntriples <= 1) return; /* nothing to sort */
|
|
if(ocdebug > 2)
|
|
storedump("initial:",store->triples,store->ntriples);
|
|
|
|
sorted = (struct OCTriple*)malloc(sizeof(struct OCTriple)*store->ntriples);
|
|
if(sorted == NULL) {
|
|
oclog(OCLOGERR,"sorttriplestore: out of memory");
|
|
return;
|
|
}
|
|
|
|
nsorted = 0;
|
|
while(nsorted < store->ntriples) {
|
|
int largest;
|
|
/* locate first non killed entry */
|
|
for(largest=0;largest<store->ntriples;largest++) {
|
|
if(store->triples[largest].key[0] != '\0') break;
|
|
}
|
|
OCASSERT(store->triples[largest].key[0] != '\0');
|
|
for(i=0;i<store->ntriples;i++) {
|
|
if(store->triples[i].key[0] != '\0') { /* avoid empty slots */
|
|
int lexorder = strcmp(store->triples[i].host,store->triples[largest].host);
|
|
int leni = strlen(store->triples[i].host);
|
|
int lenlarge = strlen(store->triples[largest].host);
|
|
/* this defines the ordering */
|
|
if(leni == 0 && lenlarge == 0) continue; /* if no urls, then leave in order */
|
|
if(leni != 0 && lenlarge == 0) largest = i;
|
|
else if(lexorder > 0) largest = i;
|
|
}
|
|
}
|
|
/* Move the largest entry */
|
|
OCASSERT(store->triples[largest].key[0] != 0);
|
|
sorted[nsorted] = store->triples[largest];
|
|
store->triples[largest].key[0] = '\0'; /* kill entry */
|
|
nsorted++;
|
|
if(ocdebug > 2)
|
|
storedump("pass:",sorted,nsorted);
|
|
}
|
|
|
|
memcpy((void*)store->triples,(void*)sorted,sizeof(struct OCTriple)*nsorted);
|
|
free(sorted);
|
|
|
|
if(ocdebug > 1)
|
|
storedump("final .rc order:",store->triples,store->ntriples);
|
|
}
|
|
|
|
/* Create a triple store from a file */
|
|
static int
|
|
ocrc_compile(const char* path)
|
|
{
|
|
char line0[MAXRCLINESIZE+1];
|
|
FILE *in_file = NULL;
|
|
int linecount = 0;
|
|
struct OCTriplestore* ocrc = &ocglobalstate.rc.ocrc;
|
|
|
|
ocrc->ntriples = 0; /* reset; nothing to free */
|
|
|
|
in_file = fopen(path, "r"); /* Open the file to read it */
|
|
if (in_file == NULL) {
|
|
oclog(OCLOGERR, "Could not open configuration file: %s",path);
|
|
return OC_EPERM;
|
|
}
|
|
|
|
for(;;) {
|
|
char *line,*key,*value;
|
|
int c;
|
|
if(!rcreadline(in_file,line0,sizeof(line0))) break;
|
|
linecount++;
|
|
if(linecount >= MAXRCLINES) {
|
|
oclog(OCLOGERR, ".rc has too many lines");
|
|
return 0;
|
|
}
|
|
line = line0;
|
|
/* check for comment */
|
|
c = line[0];
|
|
if (c == '#') continue;
|
|
rctrim(line); /* trim leading and trailing blanks */
|
|
if(strlen(line) == 0) continue;
|
|
if(strlen(line) >= MAXRCLINESIZE) {
|
|
oclog(OCLOGERR, "%s line too long: %s",path,line0);
|
|
return 0;
|
|
}
|
|
/* setup */
|
|
ocrc->triples[ocrc->ntriples].host[0] = '\0';
|
|
ocrc->triples[ocrc->ntriples].key[0] = '\0';
|
|
ocrc->triples[ocrc->ntriples].value[0] = '\0';
|
|
if(line[0] == LTAG) {
|
|
OCURI* uri;
|
|
char* url = ++line;
|
|
char* rtag = strchr(line,RTAG);
|
|
if(rtag == NULL) {
|
|
oclog(OCLOGERR, "Malformed [url] in %s entry: %s",path,line);
|
|
continue;
|
|
}
|
|
line = rtag + 1;
|
|
*rtag = '\0';
|
|
/* compile the url and pull out the host */
|
|
if(!ocuriparse(url,&uri)) {
|
|
oclog(OCLOGERR, "Malformed [url] in %s entry: %s",path,line);
|
|
continue;
|
|
}
|
|
strncpy(ocrc->triples[ocrc->ntriples].host,uri->host,MAXRCLINESIZE-1);
|
|
if(uri->port != NULL) {
|
|
strncat(ocrc->triples[ocrc->ntriples].host,":",MAXRCLINESIZE-1);
|
|
strncat(ocrc->triples[ocrc->ntriples].host,uri->port,MAXRCLINESIZE-1);
|
|
}
|
|
ocurifree(uri);
|
|
}
|
|
/* split off key and value */
|
|
key=line;
|
|
value = strchr(line, '=');
|
|
if(value == NULL)
|
|
value = line + strlen(line);
|
|
else {
|
|
*value = '\0';
|
|
value++;
|
|
}
|
|
strncpy(ocrc->triples[ocrc->ntriples].key,key,MAXRCLINESIZE);
|
|
if(*value == '\0')
|
|
strcpy(ocrc->triples[ocrc->ntriples].value,"1");/*dfalt*/
|
|
else
|
|
strncpy(ocrc->triples[ocrc->ntriples].value,value,MAXRCLINESIZE);
|
|
rctrim( ocrc->triples[ocrc->ntriples].key);
|
|
rctrim( ocrc->triples[ocrc->ntriples].value);
|
|
OCDBG2("rc: key=%s value=%s",
|
|
ocrc->triples[ocrc->ntriples].key,
|
|
ocrc->triples[ocrc->ntriples].value);
|
|
ocrc->ntriples++;
|
|
}
|
|
fclose(in_file);
|
|
sorttriplestore(&ocglobalstate.rc.ocrc);
|
|
return 1;
|
|
}
|
|
|
|
/* read and compile the rc file, if any */
|
|
OCerror
|
|
ocrc_load(void)
|
|
{
|
|
OCerror stat = OC_NOERR;
|
|
char* path = NULL;
|
|
|
|
if(ocglobalstate.rc.ignore) {
|
|
oclog(OCLOGDBG,"No runtime configuration file specified; continuing");
|
|
return OC_NOERR;
|
|
}
|
|
if(ocglobalstate.rc.loaded) return OC_NOERR;
|
|
|
|
/* locate the configuration files: first if specified,
|
|
then '.', then $HOME */
|
|
if(ocglobalstate.rc.rcfile != NULL) { /* always use this */
|
|
path = ocglobalstate.rc.rcfile;
|
|
} else {
|
|
char** rcname;
|
|
int found = 0;
|
|
for(rcname=rcfilenames;!found && *rcname;rcname++) {
|
|
stat = rc_search(".",*rcname,&path);
|
|
if(stat == OC_NOERR && path == NULL) /* try $HOME */
|
|
stat = rc_search(ocglobalstate.home,*rcname,&path);
|
|
if(stat != OC_NOERR)
|
|
goto done;
|
|
if(path != NULL)
|
|
found = 1;
|
|
}
|
|
}
|
|
if(path == NULL) {
|
|
oclog(OCLOGDBG,"Cannot find runtime configuration file; continuing");
|
|
} else {
|
|
if(ocdebug > 0)
|
|
fprintf(stderr, "RC file: %s\n", path);
|
|
if(ocrc_compile(path) == 0) {
|
|
oclog(OCLOGERR, "Error parsing %s\n",path);
|
|
stat = OC_ERCFILE;
|
|
}
|
|
}
|
|
done:
|
|
ocglobalstate.rc.loaded = 1; /* even if not exists */
|
|
if(path != NULL)
|
|
free(path);
|
|
return stat;
|
|
}
|
|
|
|
int
|
|
ocrc_process(OCstate* state)
|
|
{
|
|
int stat = 0;
|
|
char* value = NULL;
|
|
OCURI* uri = state->uri;
|
|
char* url_userpwd = NULL;
|
|
char* url_hostport = NULL;
|
|
|
|
if(!ocglobalstate.initialized)
|
|
ocinternalinitialize();
|
|
if(!ocglobalstate.rc.loaded)
|
|
ocrc_load();
|
|
/* Note, we still must do this function even if
|
|
ocglobalstate.rc.ignore is set in order
|
|
to getinfo e.g. user:pwd from url
|
|
*/
|
|
|
|
url_userpwd = uri->userpwd;
|
|
url_hostport = occombinehostport(uri);
|
|
if(url_hostport == NULL)
|
|
return OC_ENOMEM;
|
|
|
|
value = ocrc_lookup("HTTP.DEFLATE",url_hostport);
|
|
if(value != NULL) {
|
|
if(atoi(value)) state->curlflags.compress = 1;
|
|
if(ocdebug > 0)
|
|
oclog(OCLOGNOTE,"HTTP.DEFLATE: %ld", state->curlflags.compress);
|
|
}
|
|
if((value = ocrc_lookup("HTTP.VERBOSE",url_hostport)) != NULL) {
|
|
if(atoi(value)) state->curlflags.verbose = 1;
|
|
if(ocdebug > 0)
|
|
oclog(OCLOGNOTE,"HTTP.VERBOSE: %ld", state->curlflags.verbose);
|
|
}
|
|
if((value = ocrc_lookup("HTTP.TIMEOUT",url_hostport)) != NULL) {
|
|
if(atoi(value)) state->curlflags.timeout = atoi(value);
|
|
if(ocdebug > 0)
|
|
oclog(OCLOGNOTE,"HTTP.TIMEOUT: %ld", state->curlflags.timeout);
|
|
}
|
|
if((value = ocrc_lookup("HTTP.USERAGENT",url_hostport)) != NULL) {
|
|
if(atoi(value)) state->curlflags.useragent = strdup(value);
|
|
if(state->curlflags.useragent == NULL) {stat = OC_ENOMEM; goto done;}
|
|
if(ocdebug > 0)
|
|
oclog(OCLOGNOTE,"HTTP.USERAGENT: %s", state->curlflags.useragent);
|
|
}
|
|
|
|
if(
|
|
(value = ocrc_lookup("HTTP.COOKIEFILE",url_hostport))
|
|
|| (value = ocrc_lookup("HTTP.COOKIE_FILE",url_hostport))
|
|
|| (value = ocrc_lookup("HTTP.COOKIEJAR",url_hostport))
|
|
|| (value = ocrc_lookup("HTTP.COOKIE_JAR",url_hostport))
|
|
) {
|
|
state->curlflags.cookiejar = strdup(value);
|
|
if(state->curlflags.cookiejar == NULL) {stat = OC_ENOMEM; goto done;}
|
|
if(ocdebug > 0)
|
|
oclog(OCLOGNOTE,"HTTP.COOKIEJAR: %s", state->curlflags.cookiejar);
|
|
}
|
|
|
|
if((value = ocrc_lookup("HTTP.PROXY_SERVER",url_hostport)) != NULL) {
|
|
stat = ocparseproxy(state,value);
|
|
if(stat != OC_NOERR) goto done;
|
|
if(ocdebug > 0)
|
|
oclog(OCLOGNOTE,"HTTP.PROXY_SERVER: %s", value);
|
|
}
|
|
|
|
if((value = ocrc_lookup("HTTP.SSL.VALIDATE",url_hostport)) != NULL) {
|
|
if(atoi(value)) {
|
|
state->ssl.verifypeer = 1;
|
|
state->ssl.verifyhost = 1;
|
|
if(ocdebug > 0)
|
|
oclog(OCLOGNOTE,"HTTP.SSL.VALIDATE: %ld", 1);
|
|
}
|
|
}
|
|
|
|
if((value = ocrc_lookup("HTTP.SSL.CERTIFICATE",url_hostport)) != NULL) {
|
|
state->ssl.certificate = strdup(value);
|
|
if(state->ssl.certificate == NULL) {stat = OC_ENOMEM; goto done;}
|
|
if(ocdebug > 0)
|
|
oclog(OCLOGNOTE,"HTTP.SSL.CERTIFICATE: %s", state->ssl.certificate);
|
|
}
|
|
|
|
if((value = ocrc_lookup("HTTP.SSL.KEY",url_hostport)) != NULL) {
|
|
state->ssl.key = strdup(value);
|
|
if(state->ssl.key == NULL) {stat = OC_ENOMEM; goto done;}
|
|
if(ocdebug > 0)
|
|
oclog(OCLOGNOTE,"HTTP.SSL.KEY: %s", state->ssl.key);
|
|
}
|
|
|
|
if((value = ocrc_lookup("HTTP.SSL.KEYPASSWORD",url_hostport)) != NULL) {
|
|
state->ssl.keypasswd = strdup(value);
|
|
if(state->ssl.keypasswd == NULL) {stat = OC_ENOMEM; goto done;}
|
|
if(ocdebug > 0)
|
|
oclog(OCLOGNOTE,"HTTP.SSL.KEYPASSWORD: %s", state->ssl.keypasswd);
|
|
}
|
|
|
|
if((value = ocrc_lookup("HTTP.SSL.CAINFO",url_hostport)) != NULL) {
|
|
state->ssl.cainfo = strdup(value);
|
|
if(state->ssl.cainfo == NULL) {stat = OC_ENOMEM; goto done;}
|
|
if(ocdebug > 0)
|
|
oclog(OCLOGNOTE,"HTTP.SSL.CAINFO: %s", state->ssl.cainfo);
|
|
}
|
|
|
|
if((value = ocrc_lookup("HTTP.SSL.CAPATH",url_hostport)) != NULL) {
|
|
state->ssl.capath = strdup(value);
|
|
if(state->ssl.capath == NULL) {stat = OC_ENOMEM; goto done;}
|
|
if(ocdebug > 0)
|
|
oclog(OCLOGNOTE,"HTTP.SSL.CAPATH: %s", state->ssl.capath);
|
|
}
|
|
|
|
if((value = ocrc_lookup("HTTP.SSL.VERIFYPEER",url_hostport)) != NULL) {
|
|
char* s = strdup(value);
|
|
int tf = 0;
|
|
if(s == NULL || strcmp(s,"0")==0 || strcasecmp(s,"false")==0)
|
|
tf = 0;
|
|
else if(strcmp(s,"1")==0 || strcasecmp(s,"true")==0)
|
|
tf = 1;
|
|
else
|
|
tf = 1; /* default if not null */
|
|
state->ssl.verifypeer = tf;
|
|
if(ocdebug > 0)
|
|
oclog(OCLOGNOTE,"HTTP.SSL.VERIFYPEER: %d", state->ssl.verifypeer);
|
|
free(s);
|
|
}
|
|
|
|
if((value = ocrc_lookup("HTTP.NETRC",url_hostport)) != NULL) {
|
|
if(state->curlflags.netrc != NULL)
|
|
free(state->curlflags.netrc);
|
|
state->curlflags.netrc = strdup(value);
|
|
if(state->curlflags.netrc == NULL) {stat = OC_ENOMEM; goto done;}
|
|
if(ocdebug > 0)
|
|
oclog(OCLOGNOTE,"HTTP.NETRC: %s", state->curlflags.netrc);
|
|
}
|
|
|
|
{ /* Handle various cases for user + password */
|
|
/* First, see if the user+pwd was in the original url */
|
|
char* userpwd = NULL;
|
|
char* user = NULL;
|
|
char* pwd = NULL;
|
|
if(url_userpwd != NULL)
|
|
userpwd = url_userpwd;
|
|
else {
|
|
user = ocrc_lookup("HTTP.CREDENTIALS.USER",url_hostport);
|
|
pwd = ocrc_lookup("HTTP.CREDENTIALS.PASSWORD",url_hostport);
|
|
userpwd = ocrc_lookup("HTTP.CREDENTIALS.USERPASSWORD",url_hostport);
|
|
}
|
|
if(userpwd == NULL && user != NULL && pwd != NULL) {
|
|
userpwd = combinecredentials(user,pwd);
|
|
state->creds.userpwd = userpwd;
|
|
} else if(userpwd != NULL)
|
|
state->creds.userpwd = strdup(userpwd);
|
|
}
|
|
|
|
done:
|
|
if(url_hostport != NULL) free(url_hostport);
|
|
return stat;
|
|
}
|
|
|
|
static struct OCTriple*
|
|
ocrc_locate(char* key, char* hostport)
|
|
{
|
|
int i,found;
|
|
struct OCTriplestore* ocrc = &ocglobalstate.rc.ocrc;
|
|
struct OCTriple* triple;
|
|
|
|
if(ocglobalstate.rc.ignore)
|
|
return NULL;
|
|
if(!ocglobalstate.rc.loaded)
|
|
ocrc_load();
|
|
|
|
triple = ocrc->triples;
|
|
|
|
if(key == NULL || ocrc == NULL) return NULL;
|
|
if(hostport == NULL) hostport = "";
|
|
/* Assume that the triple store has been properly sorted */
|
|
for(found=0,i=0;i<ocrc->ntriples;i++,triple++) {
|
|
size_t hplen = strlen(triple->host);
|
|
int t;
|
|
if(strcmp(key,triple->key) != 0) continue; /* keys do not match */
|
|
/* If the triple entry has no url, then use it
|
|
(because we have checked all other cases)*/
|
|
if(hplen == 0) {found=1;break;}
|
|
/* do hostport match */
|
|
t = strcmp(hostport,triple->host);
|
|
if(t == 0) {found=1; break;}
|
|
}
|
|
return (found?triple:NULL);
|
|
}
|
|
|
|
char*
|
|
ocrc_lookup(char* key, char* hostport)
|
|
{
|
|
struct OCTriple* triple = ocrc_locate(key,hostport);
|
|
if(triple != NULL && ocdebug > 2) {
|
|
fprintf(stderr,"lookup %s: [%s]%s = %s\n",hostport,triple->host,triple->key,triple->value);
|
|
}
|
|
return (triple == NULL ? NULL : triple->value);
|
|
}
|
|
|
|
|
|
static void
|
|
storedump(char* msg, struct OCTriple* triples, int ntriples)
|
|
{
|
|
int i;
|
|
struct OCTriplestore* ocrc = &ocglobalstate.rc.ocrc;
|
|
|
|
if(msg != NULL) fprintf(stderr,"%s\n",msg);
|
|
if(ocrc == NULL) {
|
|
fprintf(stderr,"<EMPTY>\n");
|
|
return;
|
|
}
|
|
if(triples == NULL) triples= ocrc->triples;
|
|
if(ntriples < 0 ) ntriples= ocrc->ntriples;
|
|
for(i=0;i<ntriples;i++) {
|
|
fprintf(stderr,"\t%s\t%s\t%s\n",
|
|
(strlen(triples[i].host)==0?"--":triples[i].host),
|
|
triples[i].key,
|
|
triples[i].value);
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
/*
|
|
Lookup against all prefixes
|
|
*/
|
|
|
|
static char*
|
|
ocrc_lookup(char* suffix, char* url)
|
|
{
|
|
char* value = NULL;
|
|
char key[MAXRCLINESIZE+1];
|
|
const char** p = prefixes;
|
|
for(;*p;p++) {
|
|
if(!occopycat(key,sizeof(key),2,*p,suffix))
|
|
return NULL;
|
|
value = ocrc_lookup(key,url);
|
|
if(value != NULL)
|
|
return value;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
/* compile the rc file, if any */
|
|
static OCerror
|
|
ocreadrc(void)
|
|
{
|
|
OCerror stat = OC_NOERR;
|
|
char* path = NULL;
|
|
/* locate the configuration files: first if specified,
|
|
then '.', then $HOME */
|
|
if(ocglobalstate.rc.rcfile != NULL) { /* always use this */
|
|
path = ocglobalstate.rc.rcfile;
|
|
} else {
|
|
char** rcname;
|
|
int found = 0;
|
|
for(rcname=rcfilenames;!found && *rcname;rcname++) {
|
|
stat = rc_search(".",*rcname,&path);
|
|
if(stat == OC_NOERR && path == NULL) /* try $HOME */
|
|
stat = rc_search(ocglobalstate.home,*rcname,&path);
|
|
if(stat != OC_NOERR)
|
|
goto done;
|
|
if(path != NULL)
|
|
found = 1;
|
|
}
|
|
}
|
|
if(path == NULL) {
|
|
oclog(OCLOGDBG,"Cannot find runtime configuration file; continuing");
|
|
} else {
|
|
if(ocdebug > 0)
|
|
fprintf(stderr, "DODS RC file: %s\n", path);
|
|
if(ocdodsrc_read(path) == 0) {
|
|
oclog(OCLOGERR, "Error parsing %s\n",path);
|
|
stat = OC_ERCFILE;
|
|
}
|
|
}
|
|
done:
|
|
if(path != NULL)
|
|
free(path);
|
|
return stat;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* Prefix must end in '/'
|
|
*/
|
|
static
|
|
OCerror
|
|
rc_search(const char* prefix, const char* rcname, char** pathp)
|
|
{
|
|
char* path = NULL;
|
|
FILE* f = NULL;
|
|
int plen = strlen(prefix);
|
|
int rclen = strlen(rcname);
|
|
OCerror stat = OC_NOERR;
|
|
|
|
size_t pathlen = plen+rclen+1+1; /*+1 for '/' +1 for nul*/
|
|
path = (char*)malloc(pathlen);
|
|
if(path == NULL) {
|
|
stat = OC_ENOMEM;
|
|
goto done;
|
|
}
|
|
if(!occopycat(path,pathlen,3,prefix,"/",rcname)) {
|
|
stat = OC_EOVERRUN;
|
|
goto done;
|
|
}
|
|
/* see if file is readable */
|
|
f = fopen(path,"r");
|
|
if(f != NULL)
|
|
oclog(OCLOGDBG, "Found rc file=%s",path);
|
|
done:
|
|
if(f == NULL || stat != OC_NOERR) {
|
|
if(path != NULL)
|
|
free(path);
|
|
path = NULL;
|
|
}
|
|
if(f != NULL)
|
|
fclose(f);
|
|
if(pathp != NULL)
|
|
*pathp = path;
|
|
return OCTHROW(stat);
|
|
}
|
|
|
|
struct OCTriple*
|
|
ocrc_triple_iterate(char* key, char* url, struct OCTriple* prev)
|
|
{
|
|
struct OCTriple* next;
|
|
if(prev == NULL)
|
|
next = ocrc_locate(key,url);
|
|
else
|
|
next = prev+1;
|
|
if(next == NULL)
|
|
return NULL;
|
|
for(;next->key != NULL;next++) {
|
|
/* See if key as prefix still matches */
|
|
int cmp = strcmp(key,next->key);
|
|
if(cmp != 0) {next = NULL; break;} /* key mismatch */
|
|
/* compare url */
|
|
cmp = ocstrncmp(url,next->host,strlen(next->host));
|
|
if(cmp == 0) break;
|
|
}
|
|
return next;
|
|
}
|