1/* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
2   See the COPYRIGHT file for more information. */
3
4#include "config.h"
5#ifdef HAVE_UNISTD_H
6#include <unistd.h>
7#endif
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12#include "ocinternal.h"
13#include "ocdebug.h"
14#include "oclog.h"
15
16#define OCRCFILEENV "DAPRCFILE"
17
18#define RTAG ']'
19#define LTAG '['
20
21#define TRIMCHARS " \t\r\n"
22
23static OCerror rc_search(const char* prefix, const char* rcfile, char** pathp);
24
25static int rcreadline(FILEf, char* more, int morelen);
26static void rctrim(char* text);
27static char* combinecredentials(const char* user, const char* pwd);
28
29static void storedump(char* msg, struct OCTriple*, int ntriples);
30
31/* Define default rc files and aliases, also defines search order*/
32static char* rcfilenames[] = {".daprc",".dodsrc",NULL};
33
34/* The Username and password are in the URL if the URL is of the form:
35 * http://<name>:<passwd>@<host>/....
36 */
37static int
38occredentials_in_url(const char *url)
39{
40    char *pos = strstr(url, "http://");
41    if (!pos)
42        return 0;
43    pos += 7;
44    if (strchr(pos, '@') && strchr(pos, ':'))
45        return 1;
46    return 0;
47}
48
49static OCerror
50ocextract_credentials(const char *url, char **userpwd, char **result_url)
51{
52    OCURIparsed = NULL;
53    if(!ocuriparse(url,&parsed))
54 return OCTHROW(OC_EBADURL);
55    if(parsed->userpwd == NULL) {
56 ocurifree(parsed);
57 return OCTHROW(OC_EBADURL);
58    }
59    if(userpwd) *userpwd = strdup(parsed->userpwd);
60    ocurifree(parsed);
61    return OC_NOERR;
62}
63
64char*
65occombinehostport(const OCURIuri)
66{
67    char* hp;
68    int len = 0;
69
70    if(uri->host == NULL)
71 return NULL;
72    else
73 len += strlen(uri->host);
74    if(uri->port != NULL)
75 len += strlen(uri->port);
76    hp = (char*)malloc(len+1);
77    if(hp == NULL)
78 return NULL;
79    if(uri->port == NULL)
80        occopycat(hp,len+1,1,uri->host);
81    else
82        occopycat(hp,len+1,3,uri->host,":",uri->port);
83    return hp;
84}
85
86static char*
87combinecredentials(const char* user, const char* pwd)
88{
89    int userPassSize;
90    char *userPassword;
91
92    if(user == NULLuser = "";
93    if(pwd == NULLpwd = "";
94
95    userPassSize = strlen(user) + strlen(pwd) + 2;
96    userPassword = malloc(sizeof(char) * userPassSize);
97    if (!userPassword) {
98        oclog(OCLOGERR,"Out of Memory\n");
99 return NULL;
100    }
101    occopycat(userPassword,userPassSize-1,3,user,":",pwd);
102    return userPassword;
103}
104
105static int
106rcreadline(FILEf, char* more, int morelen)
107{
108    int i = 0;
109    int c = getc(f);
110    if(c < 0) return 0;
111    for(;;) {
112        if(i < morelen)  /* ignore excess characters */
113            more[i++]=c;
114        c = getc(f);
115        if(c < 0) break; /* eof */
116        if(c == '\n') break; /* eol */
117    }
118    /* null terminate more */
119    more[i] = '\0';
120    return 1;
121}
122
123/* Trim TRIMCHARS from both ends of text; */
124static void
125rctrim(char* text)
126{
127    char* p = text;
128    size_t len;
129    int i;
130
131    len = strlen(text);
132    /* locate first non-trimchar */
133    for(;*p;p++) {
134       if(strchr(TRIMCHARS,*p) == NULL) break; /* hit non-trim char */
135    }
136    memmove(text,p,strlen(p)+1);
137    len = strlen(text);
138    /* locate last non-trimchar */
139    if(len > 0) {
140        for(i=(len-1);i>=0;i--) {
141            if(strchr(TRIMCHARS,text[i]) == NULL) {
142                text[i+1] = '\0'; /* elide trailing trimchars */
143                break;
144            }
145        }
146    }
147}
148
149int
150ocparseproxy(OCstatestate, char* v)
151{
152    /* Do not free these; they are pointers into v; free v instead */
153    char *host_pos = NULL;
154    char *port_pos = NULL;
155    if(v == NULL || strlen(v) == 0)
156 return OC_NOERR; /* nothing there*/
157    if (occredentials_in_url(v)) {
158        char *result_url = NULL;
159        ocextract_credentials(v, &state->proxy.userpwd, &result_url);
160        v = result_url;
161    }
162    /* allocating a bit more than likely needed ... */
163    host_pos = strstr(v, "http://");
164    if (host_pos)
165        host_pos += strlen("http://");
166    else
167        host_pos = v;
168    port_pos = strchr(host_pos, ':');
169    if (port_pos) {
170        size_t host_len;
171        char *port_sep = port_pos;
172        port_pos++;
173        *port_sep = '\0';
174        host_len = strlen(host_pos);
175        state->proxy.host = malloc(sizeof(char) * host_len + 1);
176        if (state->proxy.host == NULL)
177            return OCTHROW(OC_ENOMEM);
178        strncpy(state->proxy.hosthost_poshost_len);
179        state->proxy.host[host_len] = '\0';
180        state->proxy.port = atoi(port_pos);
181    } else {
182        size_t host_len = strlen(host_pos);
183        state->proxy.host = malloc(sizeof(char) * host_len + 1);
184        if (state->proxy.host == NULL)
185            return OCTHROW(OC_ENOMEM);
186        strncpy(state->proxy.hosthost_poshost_len);
187        state->proxy.host[host_len] = '\0';
188        state->proxy.port = 80;
189    }
190#if 0
191    state->proxy.host[v_len] = '\0';
192    state->proxy.port = atoi(v);
193    s_len = strlen(v);
194    state->proxy.user = malloc(sizeof(char) * s_len + 1);
195    if (state->proxy.user == NULL)
196        return OC_ENOMEM;
197     strncpy(state->proxy.uservs_len);
198     state->proxy.user[s_len] = '\0';
199     p_len = strlen(v);
200     state->proxy.password = malloc(sizeof(char) * p_len + 1);
201     if (state->proxy.password == NULL)
202         return OCTHROW(OC_ENOMEM);
203     strncpy(state->proxy.passwordvp_len);
204     state->proxy.password[p_len] = '\0';
205#endif /*0*/
206     if (ocdebug > 1) {
207         oclog(OCLOGNOTE,"host name: %s", state->proxy.host);
208#ifdef INSECURE
209         oclog(OCLOGNOTE,"user+pwd: %s", state->proxy.userpwd);
210#endif
211         oclog(OCLOGNOTE,"port number: %d", state->proxy.port);
212    }
213    if(v) free(v);
214    return OC_NOERR;
215}
216
217/* insertion sort the triplestore based on url */
218static void
219sorttriplestore(struct OCTriplestorestore)
220{
221    int insorted;
222    struct OCTriplesorted = NULL;
223
224    if(store == NULL) return; /* nothing to sort */
225    if(store->ntriples <= 1) return; /* nothing to sort */
226    if(ocdebug > 2)
227        storedump("initial:",store->triples,store->ntriples);
228
229    sorted = (struct OCTriple*)malloc(sizeof(struct OCTriple)*store->ntriples);
230    if(sorted == NULL) {
231        oclog(OCLOGERR,"sorttriplestore: out of memory");
232        return;
233    }
234
235    nsorted = 0;
236    while(nsorted < store->ntriples) {
237        int largest;
238        /* locate first non killed entry */
239        for(largest=0;largest<store->ntriples;largest++) {
240            if(store->triples[largest].key[0] != '\0') break;
241        }
242        OCASSERT(store->triples[largest].key[0] != '\0');
243        for(i=0;i<store->ntriples;i++) {
244            if(store->triples[i].key[0] != '\0') { /* avoid empty slots */
245                int lexorder = strcmp(store->triples[i].host,store->triples[largest].host);
246                int leni = strlen(store->triples[i].host);
247                int lenlarge = strlen(store->triples[largest].host);
248                /* this defines the ordering */
249                if(leni == 0 && lenlarge == 0) continue; /* if no urls, then leave in order */
250                if(leni != 0 && lenlarge == 0) largest = i;
251                else if(lexorder > 0) largest = i;
252            }
253        }
254        /* Move the largest entry */
255        OCASSERT(store->triples[largest].key[0] != 0);
256        sorted[nsorted] = store->triples[largest];
257        store->triples[largest].key[0] = '\0'; /* kill entry */
258        nsorted++;
259      if(ocdebug > 2)
260            storedump("pass:",sorted,nsorted);
261    }
262
263    memcpy((void*)store->triples,(void*)sorted,sizeof(struct OCTriple)*nsorted);
264    free(sorted);
265
266    if(ocdebug > 1)
267        storedump("final .rc order:",store->triples,store->ntriples);
268}
269
270/* Create a triple store from a file */
271static int
272ocrc_compile(const char* path)
273{
274    char line0[MAXRCLINESIZE+1];
275    FILE *in_file = NULL;
276    int linecount = 0;
277    struct OCTriplestoreocrc = &ocglobalstate.rc.daprc;
278
279    ocrc->ntriples = 0; /* reset; nothing to free */
280
281    in_file = fopen(path, "r"); /* Open the file to read it */
282    if (in_file == NULL) {
283        oclog(OCLOGERR, "Could not open configuration file: %s",path);
284        return OC_EPERM;
285    }
286
287    for(;;) {
288        char *line,*key,*value;
289        int c;
290        if(!rcreadline(in_file,line0,sizeof(line0))) break;
291        linecount++;
292        if(linecount >= MAXRCLINES) {
293            oclog(OCLOGERR, ".rc has too many lines");
294            return 0;
295        }
296        line = line0;
297        /* check for comment */
298        c = line[0];
299        if (c == '#') continue;
300        rctrim(line);  /* trim leading and trailing blanks */
301 if(strlen(line) == 0) continue;
302        if(strlen(line) >= MAXRCLINESIZE) {
303            oclog(OCLOGERR, "%s line too long: %s",path,line0);
304            continue; /* ignore it */
305        }
306        /* setup */
307        ocrc->triples[ocrc->ntriples].host[0] = '\0';
308        ocrc->triples[ocrc->ntriples].key[0] = '\0';
309        ocrc->triples[ocrc->ntriples].value[0] = '\0';
310        if(line[0] == LTAG) {
311     OCURIuri;
312            char* url = ++line;
313            char* rtag = strchr(line,RTAG);
314            if(rtag == NULL) {
315                oclog(OCLOGERR, "Malformed [url] in %s entry: %s",path,line);
316                continue;
317            }
318            line = rtag + 1;
319            *rtag = '\0';
320            /* compile the url and pull out the host */
321     if(!ocuriparse(url,&uri)) {
322                oclog(OCLOGERR, "Malformed [url] in %s entry: %s",path,line);
323 continue;
324     }
325            strncpy(ocrc->triples[ocrc->ntriples].host,uri->host,MAXRCLINESIZE-1);
326     if(uri->port != NULL) {
327                strncat(ocrc->triples[ocrc->ntriples].host,":",MAXRCLINESIZE-1);
328                strncat(ocrc->triples[ocrc->ntriples].host,uri->port,MAXRCLINESIZE-1);
329     }
330     ocurifree(uri);
331        }
332        /* split off key and value */
333        key=line;
334        value = strchr(line, '=');
335        if(value == NULL)
336            value = line + strlen(line);
337        else {
338            *value = '\0';
339            value++;
340        }
341        strncpy(ocrc->triples[ocrc->ntriples].key,key,MAXRCLINESIZE-1);
342        if(*value == '\0')
343            strcpy(ocrc->triples[ocrc->ntriples].value,"1");/*dfalt*/
344        else
345          strncpy(ocrc->triples[ocrc->ntriples].value,value,(MAXRCLINESIZE-1));
346        rctrimocrc->triples[ocrc->ntriples].key);
347        rctrimocrc->triples[ocrc->ntriples].value);
348 OCDBG2("rc: key=%s value=%s",
349 ocrc->triples[ocrc->ntriples].key,
350 ocrc->triples[ocrc->ntriples].value);
351        ocrc->ntriples++;
352    }
353    fclose(in_file);
354    sorttriplestore(&ocglobalstate.rc.daprc);
355    return 1;
356}
357
358/* read and compile the rc file, if any */
359OCerror
360ocrc_load(void)
361{
362    OCerror stat = OC_NOERR;
363    char* path = NULL;
364
365    if(ocglobalstate.rc.ignore) {
366        oclog(OCLOGDBG,"No runtime configuration file specified; continuing");
367 return OC_NOERR;
368    }
369    if(ocglobalstate.rc.loaded) return OC_NOERR;
370
371    /* locate the configuration files in the following order:
372       1. specified by set_rcfile
373       2. set by DAPRCFILE env variable
374       3. '.'
375       4. $HOME
376    */
377    if(ocglobalstate.rc.rcfile != NULL) { /* always use this */
378 path = strdup(ocglobalstate.rc.rcfile);
379    } else if(getenv(OCRCFILEENV) != NULL && strlen(getenv(OCRCFILEENV)) > 0) {
380        path = strdup(getenv(OCRCFILEENV));
381    } else {
382 char** rcname;
383 int found = 0;
384 for(rcname=rcfilenames;!found && *rcname;rcname++) {
385     stat = rc_search(".",*rcname,&path);
386         if(stat == OC_NOERR && path == NULL)  /* try $HOME */
387         stat = rc_search(ocglobalstate.home,*rcname,&path);
388     if(stat != OC_NOERR)
389 goto done;
390     if(path != NULL)
391 found = 1;
392 }
393    }
394    if(path == NULL) {
395        oclog(OCLOGDBG,"Cannot find runtime configuration file; continuing");
396    } else {
397 if(ocdebug > 0)
398     fprintf(stderr, "RC file: %s\n", path);
399        if(ocrc_compile(path) == 0) {
400     oclog(OCLOGERR, "Error parsing %s\n",path);
401     stat = OC_ERCFILE;
402 }
403    }
404done:
405    ocglobalstate.rc.loaded = 1; /* even if not exists */
406    if(path != NULL)
407 free(path);
408    return stat;
409}
410
411OCerror
412ocrc_process(OCstatestate)
413{
414    OCerror stat = OC_NOERR;
415    char* value = NULL;
416    OCURIuri = state->uri;
417    char* url_userpwd = NULL;
418    char* url_hostport = NULL;
419
420    if(!ocglobalstate.initialized)
421 ocinternalinitialize();
422    if(!ocglobalstate.rc.loaded)
423 ocrc_load();
424    /* Note, we still must do this function even if
425       ocglobalstate.rc.ignore is set in order
426       to getinfo e.g. user:pwd from url
427    */
428
429    url_userpwd = uri->userpwd;
430    url_hostport = occombinehostport(uri);
431    if(url_hostport == NULL)
432 return OC_ENOMEM;
433
434    value = ocrc_lookup("HTTP.DEFLATE",url_hostport);
435    if(value != NULL) {
436        if(atoi(value)) state->curlflags.compress = 1;
437        if(ocdebug > 0)
438            oclog(OCLOGNOTE,"HTTP.DEFLATE: %ld", state->curlflags.compress);
439    }
440    if((value = ocrc_lookup("HTTP.VERBOSE",url_hostport)) != NULL) {
441        if(atoi(value)) state->curlflags.verbose = 1;
442        if(ocdebug > 0)
443            oclog(OCLOGNOTE,"HTTP.VERBOSE: %ld", state->curlflags.verbose);
444    }
445    if((value = ocrc_lookup("HTTP.TIMEOUT",url_hostport)) != NULL) {
446        if(atoi(value)) state->curlflags.timeout = atoi(value);
447        if(ocdebug > 0)
448            oclog(OCLOGNOTE,"HTTP.TIMEOUT: %ld", state->curlflags.timeout);
449    }
450    if((value = ocrc_lookup("HTTP.USERAGENT",url_hostport)) != NULL) {
451        if(atoi(value)) state->curlflags.useragent = strdup(value);
452        if(state->curlflags.useragent == NULL) {stat = OC_ENOMEM; goto done;}
453        if(ocdebug > 0)
454            oclog(OCLOGNOTE,"HTTP.USERAGENT: %s", state->curlflags.useragent);
455    }
456
457    if(
458          (value = ocrc_lookup("HTTP.COOKIEFILE",url_hostport))
459       || (value = ocrc_lookup("HTTP.COOKIE_FILE",url_hostport))
460       || (value = ocrc_lookup("HTTP.COOKIEJAR",url_hostport))
461       || (value = ocrc_lookup("HTTP.COOKIE_JAR",url_hostport))
462      ) {
463        state->curlflags.cookiejar = strdup(value);
464        if(state->curlflags.cookiejar == NULL) {stat = OC_ENOMEM; goto done;}
465        if(ocdebug > 0)
466            oclog(OCLOGNOTE,"HTTP.COOKIEJAR: %s", state->curlflags.cookiejar);
467    }
468
469    if((value = ocrc_lookup("HTTP.PROXY_SERVER",url_hostport)) != NULL) {
470        stat = ocparseproxy(state,value);
471        if(stat != OC_NOERR) goto done;
472        if(ocdebug > 0)
473            oclog(OCLOGNOTE,"HTTP.PROXY_SERVER: %s", value);
474    }
475
476    if((value = ocrc_lookup("HTTP.SSL.VALIDATE",url_hostport)) != NULL) {
477        if(atoi(value)) {
478     state->ssl.verifypeer = 1;
479     state->ssl.verifyhost = 1;
480            if(ocdebug > 0)
481                oclog(OCLOGNOTE,"HTTP.SSL.VALIDATE: %ld", 1);
482 }
483    }
484
485    if((value = ocrc_lookup("HTTP.SSL.CERTIFICATE",url_hostport)) != NULL) {
486        state->ssl.certificate = strdup(value);
487        if(state->ssl.certificate == NULL) {stat = OC_ENOMEM; goto done;}
488        if(ocdebug > 0)
489            oclog(OCLOGNOTE,"HTTP.SSL.CERTIFICATE: %s", state->ssl.certificate);
490    }
491
492    if((value = ocrc_lookup("HTTP.SSL.KEY",url_hostport)) != NULL) {
493        state->ssl.key = strdup(value);
494        if(state->ssl.key == NULL) {stat = OC_ENOMEM; goto done;}
495        if(ocdebug > 0)
496            oclog(OCLOGNOTE,"HTTP.SSL.KEY: %s", state->ssl.key);
497    }
498
499    if((value = ocrc_lookup("HTTP.SSL.KEYPASSWORD",url_hostport)) != NULL) {
500        state->ssl.keypasswd = strdup(value);
501        if(state->ssl.keypasswd == NULL) {stat = OC_ENOMEM; goto done;}
502        if(ocdebug > 0)
503            oclog(OCLOGNOTE,"HTTP.SSL.KEYPASSWORD: %s", state->ssl.keypasswd);
504    }
505
506    if((value = ocrc_lookup("HTTP.SSL.CAINFO",url_hostport)) != NULL) {
507        state->ssl.cainfo = strdup(value);
508        if(state->ssl.cainfo == NULL) {stat = OC_ENOMEM; goto done;}
509        if(ocdebug > 0)
510            oclog(OCLOGNOTE,"HTTP.SSL.CAINFO: %s", state->ssl.cainfo);
511    }
512
513    if((value = ocrc_lookup("HTTP.SSL.CAPATH",url_hostport)) != NULL) {
514        state->ssl.capath = strdup(value);
515        if(state->ssl.capath == NULL) {stat = OC_ENOMEM; goto done;}
516        if(ocdebug > 0)
517            oclog(OCLOGNOTE,"HTTP.SSL.CAPATH: %s", state->ssl.capath);
518    }
519
520    if((value = ocrc_lookup("HTTP.SSL.VERIFYPEER",url_hostport)) != NULL) {
521        char* s = strdup(value);
522        int tf = 0;
523        if(s == NULL || strcmp(s,"0")==0 || strcasecmp(s,"false")==0)
524            tf = 0;
525        else if(strcmp(s,"1")==0 || strcasecmp(s,"true")==0)
526            tf = 1;
527        else
528            tf = 1; /* default if not null */
529        state->ssl.verifypeer = tf;
530        if(ocdebug > 0)
531            oclog(OCLOGNOTE,"HTTP.SSL.VERIFYPEER: %d", state->ssl.verifypeer);
532 free(s);
533    }
534
535    if((value = ocrc_lookup("HTTP.NETRC",url_hostport)) != NULL) {
536        if(state->curlflags.netrc != NULL)
537     free(state->curlflags.netrc);
538        state->curlflags.netrc = strdup(value);
539        if(state->curlflags.netrc == NULL) {stat = OC_ENOMEM; goto done;}
540        if(ocdebug > 0)
541            oclog(OCLOGNOTE,"HTTP.NETRC: %s", state->curlflags.netrc);
542    }
543
544    { /* Handle various cases for user + password */
545 /* First, see if the user+pwd was in the original url */
546 char* userpwd = NULL;
547 char* user = NULL;
548 char* pwd = NULL;
549 if(url_userpwd != NULL)
550     userpwd = url_userpwd;
551 else {
552        user = ocrc_lookup("HTTP.CREDENTIALS.USER",url_hostport);
553     pwd = ocrc_lookup("HTTP.CREDENTIALS.PASSWORD",url_hostport);
554     userpwd = ocrc_lookup("HTTP.CREDENTIALS.USERPASSWORD",url_hostport);
555 }
556 if(userpwd == NULL && user != NULL && pwd != NULL) {
557     userpwd = combinecredentials(user,pwd);
558     state->creds.userpwd = userpwd;
559 } else if(userpwd != NULL)
560     state->creds.userpwd = strdup(userpwd);
561    }
562
563done:
564    if(url_hostport != NULL) free(url_hostport);
565    return stat;
566}
567
568static struct OCTriple*
569ocrc_locate(char* key, char* hostport)
570{
571    int i,found;
572    struct OCTriplestoreocrc = &ocglobalstate.rc.daprc;
573    struct OCTripletriple;
574
575    if(ocglobalstate.rc.ignore)
576 return NULL;
577    if(!ocglobalstate.rc.loaded)
578 ocrc_load();
579
580    triple = ocrc->triples;
581
582    if(key == NULL || ocrc == NULL) return NULL;
583    if(hostport == NULLhostport = "";
584    /* Assume that the triple store has been properly sorted */
585    for(found=0,i=0;i<ocrc->ntriples;i++,triple++) {
586        size_t hplen = strlen(triple->host);
587        int t;
588        if(strcmp(key,triple->key) != 0) continue; /* keys do not match */
589        /* If the triple entry has no url, then use it
590           (because we have checked all other cases)*/
591        if(hplen == 0) {found=1;break;}
592        /* do hostport match */
593        t = strcmp(hostport,triple->host);
594        if(t ==  0) {found=1; break;}
595    }
596    return (found?triple:NULL);
597}
598
599char*
600ocrc_lookup(char* key, char* hostport)
601{
602    struct OCTripletriple = ocrc_locate(key,hostport);
603    if(triple != NULL && ocdebug > 2) {
604 fprintf(stderr,"lookup %s: [%s]%s = %s\n",hostport,triple->host,triple->key,triple->value);
605    }
606    return (triple == NULL ? NULL : triple->value);
607}
608
609
610static void
611storedump(char* msg, struct OCTripletriples, int ntriples)
612{
613    int i;
614    struct OCTriplestoreocrc = &ocglobalstate.rc.daprc;
615
616    if(msg != NULL) fprintf(stderr,"%s\n",msg);
617    if(ocrc == NULL) {
618        fprintf(stderr,"<EMPTY>\n");
619        return;
620    }
621    if(triples == NULLtriplesocrc->triples;
622    if(ntriples < 0 ) ntriplesocrc->ntriples;
623    for(i=0;i<ntriples;i++) {
624        fprintf(stderr,"\t%s\t%s\t%s\n",
625                (strlen(triples[i].host)==0?"--":triples[i].host),
626                triples[i].key,
627                triples[i].value);
628    }
629}
630
631#if 0
632/*
633Lookup against all prefixes
634*/
635
636static char*
637ocrc_lookup(char* suffix, char* url)
638{
639    char* value = NULL;
640    char key[MAXRCLINESIZE+1];
641    const char** p = prefixes;
642    for(;*p;p++) {
643        if(!occopycat(key,sizeof(key),2,*p,suffix))
644            return NULL;
645 value = ocrc_lookup(key,url);
646 if(value != NULL)
647     return value;
648    }
649    return value;
650}
651
652/* compile the rc file, if any */
653static OCerror
654ocreadrc(void)
655{
656    OCerror stat = OC_NOERR;
657    char* path = NULL;
658    /* locate the configuration files: first if specified,
659       then '.',  then $HOME */
660    if(ocglobalstate.rc.rcfile != NULL) { /* always use this */
661 path = ocglobalstate.rc.rcfile;
662    } else {
663 char** rcname;
664 int found = 0;
665 for(rcname=rcfilenames;!found && *rcname;rcname++) {
666     stat = rc_search(".",*rcname,&path);
667         if(stat == OC_NOERR && path == NULL)  /* try $HOME */
668         stat = rc_search(ocglobalstate.home,*rcname,&path);
669     if(stat != OC_NOERR)
670 goto done;
671     if(path != NULL)
672 found = 1;
673 }
674    }
675    if(path == NULL) {
676        oclog(OCLOGDBG,"Cannot find runtime configuration file; continuing");
677    } else {
678 if(ocdebug > 0)
679     fprintf(stderr, "DODS RC file: %s\n", path);
680        if(ocdodsrc_read(path) == 0) {
681     oclog(OCLOGERR, "Error parsing %s\n",path);
682     stat = OC_ERCFILE;
683 }
684    }
685done:
686    if(path != NULL)
687 free(path);
688    return stat;
689}
690#endif
691
692/**
693 * Prefix must end in '/'
694 */
695static
696OCerror
697rc_search(const char* prefix, const char* rcname, char** pathp)
698{
699    char* path = NULL;
700    FILEf = NULL;
701    int plen = strlen(prefix);
702    int rclen = strlen(rcname);
703    OCerror stat = OC_NOERR;
704
705    size_t pathlen = plen+rclen+1+1; /*+1 for '/' +1 for nul*/
706    path = (char*)malloc(pathlen);
707    if(path == NULL) {
708 stat = OC_ENOMEM;
709 goto done;
710    }
711    if(!occopycat(path,pathlen,3,prefix,"/",rcname)) {
712        stat = OC_EOVERRUN;
713 goto done;
714    }
715    /* see if file is readable */
716    f = fopen(path,"r");
717    if(f != NULL)
718        oclog(OCLOGDBG, "Found rc file=%s",path);
719done:
720    if(f == NULL || stat != OC_NOERR) {
721      if(path != NULL)
722     free(path);
723      path = NULL;
724    }
725
726    if(f != NULL)
727      fclose(f);
728    if(pathp != NULL)
729      *pathp = path;
730    else {
731      free(path);
732      path = NULL;
733    }
734
735    return OCTHROW(stat);
736}
737
738struct OCTriple*
739ocrc_triple_iterate(char* key, char* url, struct OCTripleprev)
740{
741    struct OCTriplenext;
742    if(prev == NULL)
743      next = ocrc_locate(key,url);
744    else
745      next = prev+1;
746    if(next == NULL)
747      return NULL;
748    for(; strlen(next->key) > 0; next++) {
749      /* See if key as prefix still matches */
750      int cmp = strcmp(key,next->key);
751      if(cmp != 0) {next = NULL; break;} /* key mismatch */
752      /* compare url */
753      cmp = ocstrncmp(url,next->host,strlen(next->host));
754      if(cmp ==  0) break;
755    }
756    return next;
757}


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed