1 /*
2  * ===========================================================================
3  *
4  *                             COPYRIGHT NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a Government employee and thus cannot
10  *  be copyrighted.  This software/database is freely available to the
11  *  public for use without a copyright notice.  Restrictions cannot be
12  *  placed on its present or future use.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the National Library of
16  *  Medicine (NLM) and the U. S. Government do not and cannot warrant the
17  *  performance or results that may be obtained by using this software or
18  *  data.  The NLM and the U. S. Government disclaim all warranties as to
19  *  performance, merchantability or fitness for any particular purpose.
20  *
21  *  Please see that the author is suitably cited in any work or product
22  *  based on this material.
23  *
24  * ===========================================================================
25  *
26  * RCS $Id: cdconfig.c,v 6.1 1998/12/04 23:35:07 kans Exp $
27  *
28  * Author:   Jonathan Epstein
29  *
30  * Version Creation Date:   11-92
31  *
32  * File Description:
33  *  Complex configuration mechanism used in conjunction with the low-level
34  *  data access library for the Molecular Sequence Data CD-ROM library produced
35  *  by the NCBI.
36  *
37  * Modifications:
38  * --------------------------------------------------------------------------
39  * Rev   Date      Name      Description of modification
40  * ----  --------  --------  ------------------------------------------------
41  * 1.17  08-22-94  Schuler   Fixed one function not returning a value
42  *
43  *
44  * 05-19-95 Schuler     Added rcs Log directive for automatic insertion of
45  *                      modification comments.
46  *
47  * Revision $Log: cdconfig.c,v $
48  * Revision Revision 6.1  1998/12/04 23:35:07  kans
49  * Revision KludgeCdromlibGetAppParam supplies ncbi config values for psrventr
50  * Revision
51  * Revision Revision 6.0  1997/08/25 18:12:45  madden
52  * Revision Revision changed to 6.0
53  * Revision
54  * Revision Revision 5.1  1997/06/26 21:55:25  vakatov
55  * Revision [PC] DLL'd "ncbicdr.lib", "ncbiacc.lib", "ncbinacc.lib" and "ncbicacc.lib"
56  * Revision
57  * Revision Revision 5.0  1996/05/28 13:55:34  ostell
58  * Revision Set to revision 5.0
59  * Revision
60  * Revision 4.1  1995/08/24  20:44:01  epstein
61  * add more stuff for genomes
62  *
63  * Revision 4.0  1995/07/26  13:50:32  ostell
64  * force revision to 4.0
65  *
66  * Revision 1.22  1995/05/16  14:36:20  schuler
67  * Automatic comment insertion enabled
68  *
69  *
70  * ==========================================================================
71  */
72 
73 #define REVISION_STR  "$Revision: 6.1 $"
74 
75 #include <ncbi.h>
76 #include <cdromlib.h>
77 
78 /*****************************************************************************
79 *
80 *   Kludge to eliminate need for old entries in ncbi config file
81 *
82 *****************************************************************************/
83 
84 static CharPtr kludgecdromstrings [] = {
85   "ENTR_LINK.CHANNELS", "LINKS_FROM_NET",
86   "ENTR_REF.CHANNELS", "REFERENCE_FROM_NET",
87   "ENTR_SEQ.CHANNELS", "SEQUENCE_FROM_NET",
88   "ENTREZ_NET.FORMAL_NAME", "",
89   "ENTREZ_NET.RESOURCE_NAME", "Entrez",
90   "ENTREZ_NET.RESOURCE_TYPE", "Entrez",
91   "ENTREZ_NET.SERVICE_NAME", "Entrez",
92   "ENTREZ_NET.TYPE", "NET",
93   "LINKS_FROM_NET.ENTR_REF__ENTR_REF", "1",
94   "LINKS_FROM_NET.ENTR_REF__ENTR_SEQ", "1",
95   "LINKS_FROM_NET.ENTR_SEQ__ENTR_REF", "1",
96   "LINKS_FROM_NET.ENTR_SEQ__ENTR_SEQ", "1",
97   "LINKS_FROM_NET.INFO", "1",
98   "LINKS_FROM_NET.MEDIA", "ENTREZ_NET",
99   "NCBI.MEDIA", "ENTREZ_NET",
100   "REFERENCE_FROM_NET.BOOLEANS", "1",
101   "REFERENCE_FROM_NET.DOCSUMS", "1",
102   "REFERENCE_FROM_NET.MEDIA", "ENTREZ_NET",
103   "REFERENCE_FROM_NET.RECORDS", "1",
104   "REFERENCE_FROM_NET.TERMS", "1",
105   "SEQUENCE_FROM_NET.BOOLEANS", "1",
106   "SEQUENCE_FROM_NET.DOCSUMS", "1",
107   "SEQUENCE_FROM_NET.MEDIA", "ENTREZ_NET",
108   "SEQUENCE_FROM_NET.RECORDS", "1",
109   "SEQUENCE_FROM_NET.TERMS", "1",
110   NULL, NULL
111 };
112 
113 /*
114 #include <stdarg.h>
115 void CDECL   Nlm_WriteLog VPROTO((char *format, ...));
116 */
117 
KludgeCdromlibGetAppParam(CharPtr file,CharPtr section,CharPtr type,CharPtr dflt,CharPtr buf,Int2 buflen)118 static Int2 KludgeCdromlibGetAppParam (CharPtr file, CharPtr section, CharPtr type,
119                                        CharPtr dflt, CharPtr buf, Int2 buflen)
120 
121 {
122   Int2  i;
123   Char  str [256];
124 
125   if (buf == NULL || buflen < 1) return 0;
126   *buf = '\0';
127   if (dflt != NULL) {
128     StringNCpy_0 (buf, dflt, buflen);
129   }
130   if (StringICmp (file, "NCBI") != 0) return 0;
131   if (StringLen (section) > 127 || StringLen (type) > 127) return 0;
132   StringCpy (str, section);
133   StringCat (str, ".");
134   StringCat (str, type);
135   for (i = 0; kludgecdromstrings [i] != NULL; i += 2) {
136     if (StringICmp (kludgecdromstrings [i], str) == 0) {
137       StringNCpy_0 (buf, kludgecdromstrings [i + 1], buflen);
138       return StringLen (buf);
139     }
140   }
141   /*
142   GetAppParam (file, section, type, dflt, buf, buflen);
143   Nlm_WriteLog ("  \"%s.%s\", \"%s\",\n", section, type, buf);
144   */
145   return StringLen (buf);
146 }
147 
148 /*  =========================================================================
149  *      VARIABLES
150  */
151 
152 
153 static MediaPtr CurMedia = NULL;
154 static MediaPtr LRUMediaList = NULL;
155 
156 static MediaPtr MediaList = NULL;
157 static DrasticActionsPtr DrasticList = NULL;
158 static DataSourceDbPtr DataSourceDbList = NULL;
159 static DataSourceDbPtr CurDataSourceDb = NULL;
160 static int numcfginits = 0;
161 static EntrezInfoPtr MergedEntrezInfo = NULL;
162 static Boolean SoleMedia = FALSE;
163 
164 static char * sCdConfError[] =
165 {
166 #ifdef WIN_MSWIN
167     "No data source %Fs for section %Fs field %Fs"
168 #else
169     "No data source %s for section %s field %s"
170 #endif
171 };
172 
173 int _nouveau;
174 
175 
176 /*****************************************************************************
177 *
178 *   Private Function Prototypes
179 *
180 *****************************************************************************/
181 
182 static void     FreeConfig                PROTO((void));
183 static Boolean  ChangeMedia               PROTO((MediaPtr newmedia));
184 static Boolean  IsDrasticAction           PROTO((MediaPtr fromMedia,
185                                                 MediaPtr toMedia));
186 static DataSourceDbPtr LoadDataSourceInfo PROTO((CharPtr section,
187                                               CharPtr field1, CharPtr field2));
188 static void     MarkMRU                   PROTO((MediaPtr m));
189 static MediaPtr FindLRU                   PROTO((void));
190 static void     MarkLRUineligible         PROTO((MediaPtr media));
191 static void     UnMarkLRUineligible       PROTO((void));
192 static void     InitLRUeligibility        PROTO((Int2 mask));
193 static Boolean  AllCdDrivesAreFull        PROTO((void));
194 static Boolean  IsLiveMedia               PROTO((MediaPtr media));
195 
196 
197 
198 /***************************************************************************
199 *
200 *   ConfigInit()
201 *
202 *
203 ***************************************************************************/
204 
ConfigInit(void)205 NLM_EXTERN void ConfigInit(void)
206 {
207     numcfginits++;
208 }
209 
210 /***************************************************************************
211 *
212 *   ConfigFini()
213 *
214 *
215 ***************************************************************************/
216 
ConfigFini(void)217 NLM_EXTERN void ConfigFini(void)
218 {
219     if (numcfginits > 0)
220         numcfginits--;
221 
222     if (numcfginits == 0)
223         FreeConfig();
224 }
225 
226 /***************************************************************************
227 *
228 *   LoadDataSourceInfo()
229 *
230 *   Called to load from the config file the information for a given
231 *   section/field1/field2 combination, e.g., "ENTR_LINK"/"ENTR_REF"/"ENTR_SEQ",
232 *   or "ENTR_REF"/"DOCSUMS"/NULL.
233 *
234 *   The resulting data is stored as a linked list, sorted by decreasing
235 *   priority. These "DataSourceDb" lists in turn are stored, in no particular
236 *   order, in a master list, headed by DataSourceDbList.
237 *
238 ***************************************************************************/
239 
LoadDataSourceInfo(CharPtr section,CharPtr field1,CharPtr field2)240 static DataSourceDbPtr LoadDataSourceInfo (CharPtr section, CharPtr field1,
241                                            CharPtr field2)
242 {
243     DataSourceDbPtr dsdp;
244     DataSourcePtr   dsp;
245     char            channels[100];
246     CharPtr         d1;
247     CharPtr         d2;
248     CharPtr         d3;
249     CharPtr         d4;
250     CharPtr         word;
251     CharPtr         channel;
252     Boolean         no_drastic_action;
253     Boolean         done;
254     DataSourcePtr   trailptr;
255     char            buf[100];
256     Int2            priority;
257     MediaPtr        media;
258     char            field[100];
259     char            priostr[20];
260 
261     /* search the existing "data source database" to see if this entry is    */
262     /* already loaded                                                        */
263     for (dsdp = DataSourceDbList; dsdp != NULL; dsdp = dsdp->next)
264     {
265         if ((section != NULL || dsdp->key.section != NULL) &&
266             StringCmp(section, dsdp->key.section) != 0)
267             continue;
268         if ((field1 != NULL || dsdp->key.field1 != NULL) &&
269             StringCmp(field1, dsdp->key.field1) != 0)
270             continue;
271         if ((field2 != NULL || dsdp->key.field2 != NULL) &&
272             StringCmp(field2, dsdp->key.field2) != 0)
273             continue;
274 
275         /* already loaded */
276         return dsdp;
277     }
278 
279     if (KludgeCdromlibGetAppParam("NCBI", section, "CHANNELS", "", channels,
280                         sizeof(channels)) == 0)
281     {
282         return NULL; /* can't find CHANNELS keyword */
283     }
284 
285     /* insert at head of DB list (for simplicity) */
286     dsdp = (DataSourceDbPtr) MemNew(sizeof(DataSourceDb));
287     dsdp->next = DataSourceDbList;
288     DataSourceDbList = dsdp;
289 
290     dsdp->key.section = section == NULL ? NULL : StringSave(section);
291     dsdp->key.field1 = field1 == NULL ? NULL : StringSave(field1);
292 
293     StrCpy(field, field1);
294     if (field2 == NULL)
295     { /* normal case */
296         dsdp->key.field2 = NULL;
297     }
298     else { /* contraction of two fields */
299         dsdp->key.field2 = StringSave(field2);
300         StrCat(field, "__");
301         StrCat(field, field2);
302     }
303 
304     dsdp->list = NULL;
305 
306     d2 = channels;
307     StrCat (d2, "\n");
308     done = FALSE;
309 
310     /* Note that we don't use strtok() because it's not re-entrant */
311     while ((d1 = StringPBrk(d2, ",\n\r")) != NULL && !done)
312     {
313         if (*d1 == '\n' || *d1 == '\r' || *d1 == '\0')
314             done = TRUE;
315         *d1 = '\0';
316         word = d2;
317         d2 = d1 + 1;
318         d2 += StringSpn(d2, " \t"); /* remove leading spaces and tabs from next word */
319         KludgeCdromlibGetAppParam("NCBI", word, field, field2 == NULL ? "1" : "0", buf, sizeof(buf));
320         no_drastic_action = FALSE;
321 
322         /* Fields with field2 != NULL represent an NxN matrix of values; therefore,  */
323         /* we default the priorities to 0, to avoid having to declare all NxN values */
324         /* in the configuration file.                                                */
325         if (field2 == NULL)
326             priority = 1;
327         else
328             priority = 0;
329         channel = StringSave(word);
330 
331         /* Parse the field which was just read, which contains a priority    */
332         /* and may contain some other things as well.                        */
333         d4 = buf;
334         StrCat (d4, "\n");
335         if ((d3 = StringPBrk(d4, ",\n\r")) != NULL)
336         {
337             *d3 = '\0';
338             word = d4;
339             d4 = d3 + 1;
340             StrCpy(priostr, word); /* workaround for Windows */
341             priority = atoi(priostr);
342             d4 += StringSpn(d4, " \t"); /* remove leading spaces and tabs from next word */
343             if (StrCmp(d4, "NO_DRASTIC_ACTION\n") == 0)
344                 no_drastic_action = TRUE;
345         }
346 
347         if (KludgeCdromlibGetAppParam("NCBI", channel, "MEDIA", "", buf, sizeof(buf)) == 0)
348         {
349             return NULL; /* media not specified */
350         }
351         media = PreInitMedia(buf);
352 
353         /* override kludge for MEDIA; this enables a caller to make a     */
354         /* particular CHANNEL active, without needing to know any of the  */
355         /* names of the fields in that channel, except for "MEDIA"        */
356         if (StrCmp(field, "MEDIA") == 0)
357         {
358             /* the really kludgy part of the kludge is to give preference to */
359             /* network-based media; there's no good reason for this ... it   */
360             /* just makes it possible to run the multi-CD/network combo      */
361             /* version without ejecting CD-ROMs upon startup                 */
362             if (media->media_type == MEDIUM_NETWORK)
363                 priority = 1;
364             else
365                 priority = 0;
366         }
367 
368         dsp = (DataSourcePtr) MemNew(sizeof(DataSource));
369 
370         /* order list by decreasing priorities */
371         dsp->next = NULL;
372         if (dsdp->list == NULL)
373             dsdp->list = dsp;
374         else {
375             if (dsdp->list->next == NULL) /* one-element list */
376             {
377                 if (dsdp->list->priority < priority)
378                 {
379                     dsp->next = dsdp->list;
380                     dsdp->list = dsp;
381                 }
382                 else { /* inserted element had lower priority; place at end of list */
383                     dsdp->list->next = dsp;
384                 }
385             }
386             else {
387                 /* The "trailptr" points one element behind the element       */
388                 /* which is being examined, so that the new element can be    */
389                 /* inserted BEFORE the element with lower priority            */
390                 for (trailptr = dsdp->list; trailptr->next != NULL;
391                      trailptr = trailptr->next)
392                 {
393                     if (trailptr->next->priority < priority)
394                     {
395                         dsp->next = trailptr->next;
396                         trailptr->next = dsp;
397                         break;
398                     }
399                 }
400                 if (trailptr->next == NULL) /* lowest priority in list */
401                 { /* insert at end */
402                     trailptr->next = dsp;
403                 }
404 
405             }
406         }
407 
408         dsp->channel = channel;
409         dsp->priority = priority;
410         dsp->no_drastic_action = no_drastic_action;
411         dsp->media = media;
412     }
413 
414     return dsdp;
415 }
416 
417 
418 /***************************************************************************
419 *
420 *   SetSoleMedia()
421 *
422 *   For backwards-compatability with "old-style" configuration files,
423 *   we need the ability to specify a "sole media". A sole-media, by implication,
424 *   is the "valid" medium for all requested data sources, and should never
425 *   be ejected (if it is a CD-ROM, which is likely).
426 *
427 ***************************************************************************/
428 
SetSoleMedia(void)429 NLM_EXTERN void SetSoleMedia(void)
430 {
431     SoleMedia = TRUE;
432 }
433 
434 
435 /***************************************************************************
436 *
437 *   SelectDataSource()
438 *
439 *   Find a "data source" for the specified section/field1/field2 combination,
440 *   e.g., "ENTR_LINK"/"ENTR_REF"/"ENTR_SEQ", or "ENTR_REF"/"DOCSUMS"/NULL.
441 *
442 *   Returns TRUE if we are able to satisfy the request.
443 *
444 ***************************************************************************/
445 
SelectDataSource(CharPtr section,CharPtr field1,CharPtr field2)446 NLM_EXTERN Boolean SelectDataSource (CharPtr section, CharPtr field1, CharPtr field2)
447 {
448     DataSourceDbPtr dsdp;
449     DataSourcePtr dsp;
450 
451 #ifdef _NEW_CdEntrez_
452 	if (_nouveau)
453 		return TRUE;    /***** KLUDGE *****/
454 #endif
455 
456     /* for backwards compatability with "old-style" config files */
457     if (SoleMedia)
458     { /* use a single medium, rather than traversing a list */
459         CurDataSourceDb = NULL;
460         if (CurMedia == NULL)
461         { /* no media yet initialized; so initialize it */
462             if (MediaList != NULL)
463             { /* MediaList points to single media entry */
464                 return ChangeMedia(MediaList);
465             }
466             return FALSE;
467         }
468         else { /* already set-up */
469             return TRUE;
470         }
471     }
472 
473     if ((dsdp = LoadDataSourceInfo(section, field1, field2)) == NULL)
474     {
475         ErrPost (CTX_NCBICD, ERR_CD_NO_DATASRC, sCdConfError[0], "", section,
476                  field1);
477         CurDataSourceDb = NULL;
478         return FALSE;
479     }
480 
481     CurDataSourceDb = dsdp;
482 
483     if (dsdp->list == NULL)
484     {
485         ErrPost (CTX_NCBICD, ERR_CD_NO_DATASRC, sCdConfError[0], "list ",
486                  section, field1);
487         return FALSE;
488     }
489 
490     /* Mark all entries as being "not yet searched", except for "invalid" */
491     /* entries                                                            */
492     for (dsp = dsdp->list; dsp != NULL; dsp = dsp->next)
493     {
494         dsp->already_searched = dsp->media == NULL || dsp->media->invalid;
495     }
496 
497     return SelectNextDataSource();
498 }
499 
500 /***************************************************************************
501 *
502 *   SelectDataSourceByType()
503 *                  *   A short-hand mechanism for selecting the appropriate SelectDataSource()
504 *   section.
505 *
506 ****************************************************************************/
507 
SelectDataSourceByType(DocType type,CharPtr field1,CharPtr field2)508 NLM_EXTERN Boolean SelectDataSourceByType (DocType type, CharPtr field1, CharPtr field2)
509 {
510     CharPtr section;
511 
512 #ifdef _NEW_CdEntrez_
513 	if (_nouveau)
514 		return TRUE;    /***** KLUDGE *****/
515 #endif
516 
517     switch (type) {
518     case TYP_AA:
519     case TYP_NT:
520     case TYP_SEQ:
521     case TYP_ST:
522     case TYP_CH:
523         section = ENTR_SEQ_CHAN;
524         break;
525     case TYP_ML:
526         section = ENTR_REF_CHAN;
527         break;
528     default:
529         return FALSE;
530     }
531 
532     return SelectDataSource(section, field1, field2);
533 }
534 
535 /***************************************************************************
536 *
537 *   SelectDataSourceByType()
538 *
539 *   A short-hand mechanism for specifying the SelectDataSource() arguments
540 *   for the "ENTR_LINK" section. Note that entries in the "ENTR_LINK" section
541 *   are specified by the "from-type" name, followed by two underscores, followed
542 *   by the "to-type" name.
543 *
544 ****************************************************************************/
545 
SelectDataLinksByTypes(DocType type,DocType link_to_type)546 NLM_EXTERN Boolean SelectDataLinksByTypes (DocType type, DocType link_to_type)
547 {
548     CharPtr field1;
549     CharPtr field2;
550 
551 #ifdef _NEW_CdEntrez_
552 	if (_nouveau)
553 		return TRUE;    /***** KLUDGE *****/
554 #endif
555 
556     switch (type) {
557     case TYP_AA:
558     case TYP_NT:
559     case TYP_SEQ:
560     case TYP_ST:
561     case TYP_CH:
562         field1 = ENTR_SEQ_CHAN;
563         break;
564     case TYP_ML:
565         field1 = ENTR_REF_CHAN;
566         break;
567     default:
568         return FALSE;
569     }
570 
571     switch (link_to_type) {
572     case TYP_AA:
573     case TYP_NT:
574     case TYP_SEQ:
575     case TYP_ST:
576     case TYP_CH:
577         field2 = ENTR_SEQ_CHAN;
578         break;
579     case TYP_ML:
580         field2 = ENTR_REF_CHAN;
581         break;
582     default:
583         return FALSE;
584     }
585 
586     return SelectDataSource(ENTR_LINKS_CHAN, field1, field2);
587 }
588 
589 /***************************************************************************
590 *
591 *   SelectNextDataSource()
592 *
593 *   Called subsequent to SelectDataSource(), to find the next {or first,
594 *   when called by SelectDataSource()} available data source for the
595 *   previously selected section/field1/field2 combination.
596 *
597 ****************************************************************************/
598 
SelectNextDataSource(void)599 NLM_EXTERN Boolean SelectNextDataSource (void)
600 {
601     DataSourceDbPtr dsdp = CurDataSourceDb;
602     DataSourcePtr dsp;
603     DataSourcePtr best_entry;
604     DataSourcePtr best_on_live_media;
605 
606 #ifdef _NEW_CdEntrez_
607 	if (_nouveau)
608 		return FALSE;    /***** KLUDGE *****/
609 #endif
610 
611     if (dsdp == NULL)
612     { /* no current data source "database" */
613         return FALSE;
614     }
615 
616     /* loop forever (until return) */
617     while (TRUE)
618     {
619         best_on_live_media = NULL;
620 
621         /* Try to find an entry associated with the current media, provided  */
622         /* the current media is a live media (select the one which appears   */
623         /* first in the list, and thus has the highest priority              */
624         for (dsp = dsdp->list; dsp != NULL; dsp = dsp->next)
625         {
626             if (dsp->priority > 0 && !dsp->already_searched &&
627                 dsp->media == CurMedia && IsLiveMedia(dsp->media))
628             {
629                 best_on_live_media = dsp;
630                 break;
631             }
632         }
633 
634         /* Try to find an entry associated with a live media (select         */
635         /* the one which appears first in the list, and thus has the highest */
636         /* priority).                                                        */
637         for (dsp = dsdp->list; best_on_live_media == NULL && dsp != NULL;
638              dsp = dsp->next)
639         {
640             if (dsp->priority > 0 && !dsp->already_searched &&
641                 IsLiveMedia(dsp->media))
642             {
643                 best_on_live_media = dsp;
644                 break;
645             }
646         }
647 
648         /* Search for an entry with a higher priority than that associated   */
649         /* with best_on_live_media, for which drastic-actions are not         */
650         /* disallowed (unless switching to that media is not a "drastic      */
651         /* action")                                                          */
652         best_entry = best_on_live_media;
653 
654         for (dsp = dsdp->list; dsp != NULL && dsp->priority > 0; dsp = dsp->next)
655         {
656             if (dsp->already_searched)
657                 continue;
658 
659             if (best_on_live_media != NULL &&
660                 dsp->priority <= best_on_live_media->priority)
661             {
662                 break; /* nothing found better than the "live" media */
663             }
664 
665             if (!(dsp->no_drastic_action) || best_on_live_media == NULL ||
666                 !IsDrasticAction(CurMedia, dsp->media))
667             { /* found a better medium */
668                 best_entry = dsp;
669                 break;
670             }
671         }
672 
673         if (best_entry == NULL)
674         {
675             return FALSE;
676         }
677 
678         for (dsp = dsdp->list; dsp != NULL; dsp = dsp->next)
679         { /* mark all entries associated with this media as "already searched" */
680             if (dsp->media == best_entry->media)
681                 dsp->already_searched = TRUE;
682         }
683 
684         if (best_entry->media != CurMedia)
685         {
686             if (ChangeMedia (best_entry->media))
687                 return TRUE;
688         }
689         else { /* the current Media was fine */
690             return TRUE;
691         }
692     }
693 }
694 
695 /***************************************************************************
696 *
697 *   FreeConfig()
698 *
699 *   Free and reset all configuration data. This should be used sparingly
700 *   since it resets all configuration information gathered to date.
701 *
702 ****************************************************************************/
703 
FreeConfig(void)704 static void FreeConfig(void)
705 {
706     MediaPtr mp, nextmp;
707     DataSourceDbPtr dsdp, nextdsdp;
708     DataSourcePtr dsp, nextdsp;
709     DrasticActionsPtr dap, nextdap;
710     CdMediaInfoPtr cmip;
711     Int2 i;
712 
713     /* Free all the dynamically allocated lists of config data */
714 
715     for (mp = MediaList; mp != NULL; mp = nextmp)
716     {
717         MemFree(mp->media_alias);
718         MemFree(mp->formal_name);
719 
720         if (mp != CurMedia)
721         { /* CdFini()/NetFini() will take care of this for us for CurMedia */
722             EntrezInfoFree(mp->entrez_info);
723         }
724 
725         switch(mp->media_type) {
726         case MEDIUM_CD:
727         case MEDIUM_DISK:
728             cmip = (CdMediaInfoPtr) mp->media_info;
729 
730             if (cmip == NULL)
731                 break;
732             if (cmip->device_name != NULL)
733                 MemFree (cmip->device_name);
734             if (cmip->mount_point != NULL)
735                 MemFree (cmip->mount_point);
736             if (cmip->mount_cmd != NULL)
737                 MemFree (cmip->mount_cmd);
738             if (mp != CurMedia)
739             { /* CdFini() will take care of this for us for CurMedia */
740                 for (i = 0; i < NDIR; i++)
741                 {
742                     if (cmip->sPath[i] != NULL)
743                         MemFree(cmip->sPath[i]);
744                 }
745             } else {
746                 /* to avoid future references to a freed data structure */
747                 CurMedia = NULL;
748             }
749 
750             break;
751         default:
752             break;
753         }
754         MemFree(mp->media_info);
755         nextmp = mp->next;
756         MemFree(mp);
757     }
758 
759     MediaList = NULL;
760     CurMedia = NULL;
761     LRUMediaList = NULL;
762 
763     for (dsdp = DataSourceDbList; dsdp != NULL; dsdp = nextdsdp)
764     {
765         MemFree(dsdp->key.section);
766         MemFree(dsdp->key.field1);
767         MemFree(dsdp->key.field2);
768         /* Each DataSourceDbList entry references one or more DataSource */
769         /* entries                                                       */
770         for (dsp = dsdp->list; dsp != NULL; dsp = nextdsp)
771         {
772             MemFree(dsp->channel);
773             nextdsp = dsp->next;
774             MemFree(dsp);
775         }
776         nextdsdp = dsdp->next;
777         MemFree(dsdp);
778     }
779 
780     DataSourceDbList = NULL;
781 
782     for (dap = DrasticList; dap != NULL; dap = nextdap)
783     {
784         nextdap = dap->next;
785         MemFree(dap);
786     }
787 
788     DrasticList = NULL;
789 
790     if (MergedEntrezInfo != NULL)
791         EntrezInfoFree (MergedEntrezInfo);
792     MergedEntrezInfo = NULL;
793     SoleMedia = FALSE;
794 }
795 
796 /***************************************************************************
797 *
798 *   GetCurMedia()
799 *
800 *   Obtain the current media. Provided to allow the CurMedia variable to be
801 *   "hidden" within this file.
802 *
803 ****************************************************************************/
804 
GetCurMedia(void)805 NLM_EXTERN MediaPtr GetCurMedia (void)
806 {
807     return CurMedia;
808 }
809 
810 /***************************************************************************
811 *
812 *   CurMediaType()
813 *
814 *   Obtain the current media type, or MEDIUM_UNKNOWN, if the media type has
815 *   not yet been set.
816 *
817 ****************************************************************************/
818 
CurMediaType(void)819 NLM_EXTERN Int2 CurMediaType (void)
820 {
821 
822 #ifdef _NEW_CdEntrez_
823 	if (_nouveau)
824 		return MEDIUM_CD;    /***** KLUDGE *****/
825 #endif
826 
827 
828     if (CurMedia == NULL)
829         return MEDIUM_UNKNOWN;
830 
831     return CurMedia->media_type;
832 }
833 
834 /***************************************************************************
835 *
836 *   SetCurMedia()
837 *
838 *   Set the current media. Provided to allow the CurMedia variable to be
839 *   "hidden" within this file. To be used cautiously.
840 *
841 ****************************************************************************/
842 
SetCurMedia(MediaPtr NewMedia)843 NLM_EXTERN MediaPtr SetCurMedia (MediaPtr NewMedia)
844 {
845     CurMedia = NewMedia;
846     return CurMedia;
847 }
848 
849 /***************************************************************************
850 *
851 *   IsDrasticAction()
852 *
853 *   Used to see whether a switch between two media is considered to be a
854 *   "drastic action", i.e., something to be avoided. When it becomes known
855 *   whether a given switch is considered to be "drastic", that information
856 *   is stored in a linked list. Requests which cannot be satisfied from that
857 *   list are searched in the configuration file, and the results are
858 *   subsequently stored in that list.
859 *
860 ****************************************************************************/
861 
IsDrasticAction(MediaPtr fromMedia,MediaPtr toMedia)862 static Boolean IsDrasticAction(MediaPtr fromMedia, MediaPtr toMedia)
863 {
864     DrasticActionsPtr d;
865     char drastic_to[60];
866     char buf[10];
867 
868     /* First try to obtain "drastic" information from a cached list */
869     for (d = DrasticList; d != NULL; d = d->next)
870     {
871         if (d->from_media == fromMedia && d->to_media == toMedia)
872             return d->is_drastic;
873     }
874 
875     /* If unable to find it on the cached list, search the config file */
876     /* and then add the information to the cached list                 */
877 
878     StrCpy(drastic_to, "DRASTIC_TO_");
879     StrCat(drastic_to, toMedia->media_alias);
880 
881     d = (DrasticActionsPtr) MemNew(sizeof(DrasticActions));
882     d->from_media = fromMedia;
883     d->to_media = toMedia;
884     d->is_drastic = KludgeCdromlibGetAppParam("NCBI", fromMedia->media_alias, drastic_to,
885                                      "", buf, sizeof(buf)) > 0;
886     d->next = DrasticList;
887     DrasticList = d;
888     return d->is_drastic;
889 }
890 
891 /***************************************************************************
892 *
893 *   ChangeMedia()
894 *
895 *   Make the specified media the "active" media. This requires "swapping out"
896 *   the old media, if one is active, and may require, e.g., ejecting a CD-ROM
897 *   to make room for a new one.
898 *
899 ****************************************************************************/
900 
ChangeMedia(MediaPtr newMedia)901 static Boolean ChangeMedia(MediaPtr newMedia)
902 {
903     if (newMedia == NULL)
904         return FALSE;
905 
906     if (newMedia == CurMedia)
907         return TRUE;
908 
909     if (CurMedia != NULL)
910     {
911         CurMedia->is_live = FALSE;
912     }
913 
914     if (newMedia->media_type == MEDIUM_CD)
915     {
916         MediaPtr toBeEjected;
917         CdMediaInfoPtr cdm;
918         char msg[100];
919         Int2 numTries = 0;
920 
921         InitLRUeligibility(MEDIUM_CD);
922         /* the media which we want to be inserted is ineligible for ejection */
923         MarkLRUineligible(newMedia);
924 
925         while (! CdIsInserted(newMedia))
926         {
927             if (numTries++ > 3)
928                 return FALSE;
929             if (AllCdDrivesAreFull())
930             {
931                 if ((toBeEjected = FindLRU()) != NULL)
932                 { /* it's the user's problem if there are none to be ejected */
933                     MarkLRUineligible(toBeEjected);
934                     if (toBeEjected->media_type == MEDIUM_CD &&
935                         CdIsInserted(toBeEjected) &&
936                         (cdm = (CdMediaInfoPtr) toBeEjected->media_info) !=
937                         NULL)
938                     {
939                         if (toBeEjected->entrez_info != NULL)
940                         {
941                             EjectCd(toBeEjected->entrez_info->volume_label,
942                                     cdm->device_name, cdm->raw_device_name,
943                                     cdm->mount_point, cdm->mount_cmd);
944                         }
945                     }
946                 }
947             }
948 
949             StrCpy (msg, "Please insert <");
950             StrCat (msg, newMedia->formal_name);
951             StrCat (msg, ">; select OK when ready");
952             if (Message(MSG_OKC, msg) == ANS_CANCEL)
953             {
954                 return FALSE;
955             }
956 
957             if ((cdm = (CdMediaInfoPtr) newMedia->media_info) != NULL &&
958                 newMedia->entrez_info != NULL)
959             {
960                 MountCd(newMedia->entrez_info->volume_label, cdm->device_name,
961                         cdm->mount_point, cdm->mount_cmd);
962             }
963         }
964     }
965 
966     if (CurMedia != NULL && CurMedia->swapOutMedia != NULL)
967     {
968         CurMedia->swapOutMedia(CurMedia);
969     }
970     if (newMedia->swapInMedia != NULL)
971     {
972         newMedia->swapInMedia(newMedia);
973     }
974     MarkMRU(newMedia);
975 
976     CurMedia = newMedia;
977     CurMedia->is_live = TRUE;
978     return TRUE;
979 }
980 
981 /***************************************************************************
982 *
983 *   PreInitMedia()
984 *
985 *   Perform the pre-initialization of a media. This is the initialization which
986 *   which may be performed when, e.g., a Network Service is not yet available,
987 *   or a CD-ROM is not yet inserted into a CD-ROM drive. Subsequently
988 *   initialization may be performed at a later time  when the media becomes
989 *   fully available.
990 *
991 ****************************************************************************/
992 
PreInitMedia(CharPtr mediaName)993 NLM_EXTERN MediaPtr PreInitMedia (CharPtr mediaName)
994 {
995     char buf[80];
996     MediaPtr m;
997 
998     for (m = MediaList; m != NULL; m = m->next)
999     {
1000         if (StrCmp(mediaName, m->media_alias) == 0)
1001             return m; /* already have it */
1002     }
1003 
1004     if (KludgeCdromlibGetAppParam("NCBI", mediaName, "TYPE", "", buf, sizeof(buf)) == 0 && !SoleMedia)
1005         return NULL;
1006 
1007     m = (MediaPtr) MemNew(sizeof(Media));
1008 
1009     m->media_type = MEDIUM_UNKNOWN;
1010     if (SoleMedia)
1011         m->media_type = MEDIUM_DISK;
1012 
1013     if (StrCmp(buf, "CD") == 0)
1014         m->media_type = MEDIUM_CD;
1015     if (StrCmp(buf, "NET") == 0)
1016         m->media_type = MEDIUM_NETWORK;
1017     if (StrCmp(buf, "HARDDISK") == 0)
1018         m->media_type = MEDIUM_DISK;
1019 
1020     if (KludgeCdromlibGetAppParam("NCBI", mediaName, "FORMAL_NAME", "", buf, sizeof(buf)) != 0)
1021     {
1022         m->formal_name = StringSave(buf);
1023     }
1024     else {
1025         m->formal_name = StringSave(mediaName);
1026     }
1027 
1028     m->inited_partial = FALSE;
1029     m->inited_total = FALSE;
1030     m->invalid = FALSE;
1031     m->in_use = FALSE;
1032     m->is_live = FALSE;
1033     m->media_info = NULL;
1034     m->swapOutMedia = NULL;
1035     m->swapInMedia = NULL;
1036     m->finiMedia = NULL;
1037     m->media_alias = StringSave(mediaName);
1038     m->next = MediaList;
1039     m->LRUineligible = FALSE;
1040     if (LRUMediaList == NULL)
1041     { /* now a single element in the list */
1042         m->next_lru = m;
1043         m->prev_lru = m;
1044     }
1045     else { /* insert into double-linked circular list */
1046         m->prev_lru = LRUMediaList->prev_lru;
1047         m->next_lru = LRUMediaList;
1048         LRUMediaList->prev_lru->next_lru = m;
1049         LRUMediaList->prev_lru = m;
1050     }
1051     LRUMediaList = m;
1052     MediaList = m;
1053 
1054     return m;
1055 }
1056 
1057 /***************************************************************************
1058 *
1059 *   CdIsInserted()
1060 *
1061 *   Test to see whether the specified CD-ROM is currently inserted into a
1062 *   CD-ROM drive.
1063 *
1064 ****************************************************************************/
1065 
CdIsInserted(MediaPtr media)1066 NLM_EXTERN Boolean CdIsInserted(MediaPtr media)
1067 {
1068     Boolean retval = FALSE;
1069 #ifdef _OLD_CdEntrez_
1070     CdMediaInfoPtr cdm;
1071     AsnIoPtr aip;
1072     EntrezInfoPtr vi;
1073     EntrezInfoPtr pre_init_vi;
1074     ErrDesc err;
1075     short erract;
1076 #endif
1077 
1078 #ifdef _NEW_CdEntrez_
1079 	if (_nouveau)
1080 		retval = TRUE;    /***** KLUDGE *****/
1081 #endif
1082 
1083 #ifdef _OLD_CdEntrez_
1084     if (media == NULL)
1085         return FALSE;
1086     if (media->is_live)
1087         return TRUE;
1088     if ( (cdm = (CdMediaInfoPtr) media->media_info) == NULL)
1089         return FALSE;
1090     if ( (pre_init_vi = media->entrez_info) == NULL)
1091         return FALSE;
1092 
1093     ErrGetOpts(&erract, NULL);
1094     ErrSetOpts(ERR_IGNORE, 0);
1095 
1096     if ((aip = EntrezInfoOpen(cdm->sPath[DIR_ROOT])) != NULL)
1097     {
1098         vi = EntrezInfoAsnRead(aip, NULL);
1099         AsnIoClose(aip);
1100         if (vi != NULL)
1101         {
1102             if (StrCmp(vi->volume_label, pre_init_vi->volume_label) ==
1103                 0 &&
1104                 vi->version == pre_init_vi->version &&
1105                 vi->issue == pre_init_vi->issue &&
1106                 vi->format == pre_init_vi->format)
1107                 retval = TRUE;
1108             EntrezInfoFree(vi);
1109         }
1110     }
1111     else {
1112         ErrFetch(&err); /* discard error */
1113     }
1114 
1115     ErrSetOpts(erract, 0); /* restore previous error status */
1116 
1117 #endif
1118     return retval;
1119 }
1120 
1121 /***************************************************************************
1122 *
1123 *   EntrezInfoMerge()
1124 *
1125 *   Perform an "optomistic merge" of all the available EntrezInfo data
1126 *   from the different known media. If there is only a single known medium,
1127 *   then this degrades to returning the EntrezInfo for that medium. Otherwise,
1128 *   the "type" entries with the maximum amount of sub-entries are selected.
1129 *
1130 ****************************************************************************/
1131 
EntrezInfoMerge(void)1132 NLM_EXTERN  EntrezInfoPtr EntrezInfoMerge(void)
1133 {
1134     EntrezInfoPtr new;
1135     Int2 MaxTypes = 0;
1136     MediaPtr mp;
1137     Int2 i;
1138     Int2 f;
1139     EntrezInfoPtr cip;
1140     EntrezInfoPtr InfoWithMaxTypes;
1141     EntrezTypeDataPtr besttype;
1142     Int4 count;
1143     Int2 mediaCount = 0;
1144 
1145     /* first, find out how many types there are, and save a pointer to an */
1146     /* entry which has that many types                                    */
1147     for (mp = MediaList; mp != NULL; mp = mp->next)
1148     {
1149         if ( (cip = mp->entrez_info) == NULL)
1150             continue;
1151         mediaCount++;
1152         if (cip->type_count <= MaxTypes)
1153             continue;
1154         MaxTypes = cip->type_count;
1155         InfoWithMaxTypes = cip;
1156     }
1157 
1158     if (MaxTypes == 0)
1159         return NULL;
1160 
1161     if (MergedEntrezInfo != NULL)
1162         EntrezInfoFree(MergedEntrezInfo);
1163 
1164     new = (EntrezInfoPtr) MemNew(sizeof(EntrezInfo));
1165     MergedEntrezInfo = new;
1166     new->volume_label = StringSave(InfoWithMaxTypes->volume_label);
1167     new->version = InfoWithMaxTypes->version;
1168     new->issue = InfoWithMaxTypes->issue;
1169     new->format = InfoWithMaxTypes->format;
1170     new->descr = StringSave(InfoWithMaxTypes->descr);
1171 
1172     /* there is no way to merge compression information if there is more than */
1173     /* one medium                                                             */
1174     if (mediaCount <= 1 && ! InfoWithMaxTypes->no_compression) {
1175         new->no_compression = InfoWithMaxTypes->no_compression;
1176         new->huff_count = InfoWithMaxTypes->huff_count;
1177         new->huff_left = MemDup (InfoWithMaxTypes->huff_left,
1178                                  sizeof(new->huff_left[0]) * new->huff_count);
1179         new->huff_right = MemDup (InfoWithMaxTypes->huff_right,
1180                                   sizeof(new->huff_right[0]) * new->huff_count);
1181     } else {
1182         new->no_compression = TRUE;
1183         new->huff_count = 0;
1184         new->huff_left = NULL;
1185         new->huff_right = NULL;
1186     }
1187 
1188     new->type_count = MaxTypes;
1189     new->type_bucket_size = InfoWithMaxTypes->type_bucket_size;
1190     new->field_count = InfoWithMaxTypes->field_count;
1191     new->field_bucket_size = InfoWithMaxTypes->field_bucket_size;
1192 
1193     new->type_names = (CharPtr PNTR) MemNew(sizeof(CharPtr) * MaxTypes);
1194     new->field_names = (CharPtr PNTR) MemNew(sizeof(CharPtr) *
1195                         new->field_count);
1196     new->types = (EntrezTypeDataPtr) MemNew(sizeof(EntrezTypeData) * MaxTypes);
1197     if (InfoWithMaxTypes->type_info != NULL)
1198     {
1199         new->type_info = (EntrezTypeInfo PNTR) MemNew(sizeof(EntrezTypeInfo) * MaxTypes);
1200     }
1201     if (InfoWithMaxTypes->field_info != NULL)
1202     {
1203         new->field_info = (EntrezFieldInfo PNTR)
1204                              MemNew(sizeof(EntrezFieldInfo) *
1205                              InfoWithMaxTypes->field_count);
1206     }
1207 
1208     for (i = 0; i < InfoWithMaxTypes->field_count; i++)
1209     {
1210         new->field_names[i] = StringSave(InfoWithMaxTypes->field_names[i]);
1211         if (new->field_info != NULL)
1212         {
1213             new->field_info[i] = InfoWithMaxTypes->field_info[i];
1214             new->field_info[i].name = StringSave(InfoWithMaxTypes->field_info[i].name);
1215             new->field_info[i].descr = StringSave(InfoWithMaxTypes->field_info[i].descr);
1216         }
1217     }
1218 
1219     for (i = 0; i < MaxTypes; i++)
1220     {
1221         new->type_names[i] = StringSave(InfoWithMaxTypes->type_names[i]);
1222         if (new->type_info != NULL)
1223         {
1224             new->type_info[i].id = InfoWithMaxTypes->type_info[i].id;
1225             StrCpy(new->type_info[i].tag,InfoWithMaxTypes->type_info[i].tag);
1226             new->type_info[i].name = StringSave(InfoWithMaxTypes->type_info[i].name);
1227             new->type_info[i].descr = StringSave(InfoWithMaxTypes->type_info[i].descr);
1228             new->type_info[i].asntype = StringSave(InfoWithMaxTypes->type_info[i].asntype);
1229         }
1230 
1231         count = 0;
1232 
1233         /* for each "type", traverse the media list and find the "best" one */
1234         for (mp = MediaList; mp != NULL; mp = mp->next)
1235         {
1236             if ( (cip = mp->entrez_info) == NULL)
1237                 continue;
1238             if (cip->type_count < i)
1239                 continue;
1240             if (cip->types[i].num < count)
1241                 continue;
1242             /* the "best" type is the one with the most entries */
1243             besttype = &(cip->types[i]);
1244             count = besttype->num;
1245         }
1246         new->types[i].num = besttype->num;
1247         new->types[i].num_uids = besttype->num_uids;
1248         new->types[i].minuid = besttype->minuid;
1249         new->types[i].maxuid = besttype->maxuid;
1250         new->types[i].num_bucket = besttype->num_bucket;
1251         new->types[i].fields = (EntrezFieldDataPtr) MemNew(
1252                                 sizeof(EntrezFieldData) *
1253                                 InfoWithMaxTypes->field_count);
1254         for (f = 0; f < InfoWithMaxTypes->field_count; f++)
1255         {
1256             new->types[i].fields[f].num_terms =
1257                                     besttype->fields[f].num_terms;
1258             new->types[i].fields[f].num_bucket =
1259                                     besttype->fields[f].num_bucket;
1260         }
1261 
1262     }
1263 
1264     return new;
1265 }
1266 
1267 /***************************************************************************
1268 *
1269 *   FindLRU()
1270 *
1271 *   Find the "least-recently-used" entry in a doubly-linked-queue of media,
1272 *   with the additional constraint that the selected medium may not be marked
1273 *   as "ineligible".
1274 *
1275 ****************************************************************************/
1276 
FindLRU(void)1277 static MediaPtr FindLRU(void)
1278 {
1279     MediaPtr media;
1280 
1281     if (LRUMediaList == NULL)
1282         return NULL;
1283 
1284     media = LRUMediaList;
1285 
1286     /* traverse media list, beginning with Least-Recently-Used, searching for an */
1287     /* eligible candidate                                                        */
1288     do {
1289         media = media->prev_lru;
1290         if (! media->LRUineligible)
1291             return media;
1292     } while (media != NULL && media != LRUMediaList);
1293 
1294     return NULL;
1295 }
1296 
1297 /***************************************************************************
1298 *
1299 *   MarkLRUineligible()
1300 *
1301 *   Mark a medium as "ineligible" to be considered in a search for a
1302 *   least-recently-used medium.
1303 *
1304 ****************************************************************************/
1305 
MarkLRUineligible(MediaPtr media)1306 static void MarkLRUineligible(MediaPtr media)
1307 {
1308     if (media != NULL)
1309     {
1310         media->LRUineligible = TRUE;
1311     }
1312 }
1313 
1314 /***************************************************************************
1315 *
1316 *   InitLRUeligibility()
1317 *
1318 *   Mark all media as not-"ineligible", i.e., eligible, to be considered
1319 *   in a search for the least-recently-used medium ... provided that they
1320 *   are of the specified media-type. All other media are ineligible.
1321 *
1322 ****************************************************************************/
1323 
InitLRUeligibility(Int2 mask)1324 static void InitLRUeligibility(Int2 mask)
1325 {
1326     MediaPtr m = LRUMediaList;
1327 
1328     if (m == NULL)
1329         return;
1330 
1331     do {
1332         if (m->media_type & mask)
1333             m->LRUineligible = FALSE;
1334         else
1335             m->LRUineligible = TRUE;
1336         m = m->next_lru;
1337     } while (m != LRUMediaList);
1338 }
1339 
1340 /***************************************************************************
1341 *
1342 *   MarkMRU()
1343 *
1344 *   Mark this medium as the "most-recently-used" by moving it to the
1345 *   head (or tail, depending upon how you look at it) of a doubly-linked
1346 *   queue.
1347 *
1348 ****************************************************************************/
1349 
MarkMRU(MediaPtr m)1350 static void MarkMRU(MediaPtr m)
1351 { /* mark this entry as most recently used by moving to head of Queue */
1352 
1353     if (m == NULL || LRUMediaList == NULL)
1354         return;
1355 
1356     /* already Most-Recently-Used; and besides, the algorithm that follows  */
1357     /* will produce spaghetti if m already points to the head of the queue  */
1358     if (m == LRUMediaList)
1359         return;
1360 
1361     /* delete entry from neighbors' links */
1362     m->prev_lru->next_lru = m->next_lru;
1363     m->next_lru->prev_lru = m->prev_lru;
1364 
1365     /* insert at beginning of list */
1366     m->prev_lru = LRUMediaList->prev_lru;
1367     m->next_lru = LRUMediaList;
1368     LRUMediaList->prev_lru->next_lru = m;
1369     LRUMediaList->prev_lru = m;
1370     LRUMediaList = m;
1371 }
1372 
1373 /***************************************************************************
1374 *
1375 *   AllCdDrivesAreFull()
1376 *
1377 *   Returns TRUE if all availabe CD-ROM drives are currently full. This
1378 *   should be done by searching the known CD-ROM drives for a "vacancy",
1379 *   but this is currently difficult to perform.
1380 *
1381 ****************************************************************************/
1382 
AllCdDrivesAreFull(void)1383 static Boolean AllCdDrivesAreFull(void)
1384 { /* for now, be pessimistic */
1385     return TRUE;
1386 }
1387 
1388 /***************************************************************************
1389 *
1390 *   IsLiveMedia()
1391 *
1392 *   Indicates whether the specified media is "live". This means either,
1393 *   e.g., a currently inserted CD-ROM, or a currently active network service,
1394 *   etc.
1395 *
1396 ****************************************************************************/
1397 
IsLiveMedia(MediaPtr media)1398 static Boolean  IsLiveMedia (MediaPtr media)
1399 {
1400     if (media == NULL)
1401         return FALSE;
1402 
1403     if (media->invalid)
1404         return FALSE;
1405 
1406     if (media->media_type == MEDIUM_DISK)
1407         return CdIsInserted(media);
1408 
1409     if (media->media_type == MEDIUM_CD)
1410         return CdIsInserted(media);
1411 
1412     if (media->media_type == MEDIUM_NETWORK)
1413         return TRUE;
1414 
1415     /* else */
1416     return FALSE;
1417 }
1418 
ParseMedia(ConfCtlProc initfunc,Int2 media_mask)1419 NLM_EXTERN Int2 ParseMedia(ConfCtlProc initfunc, Int2 media_mask)
1420 {
1421     char media[256];
1422     CharPtr m1,m2;
1423     CharPtr word;
1424     Boolean done;
1425     MediaPtr mp;
1426     Int2 numProcessed = 0;
1427 
1428     KludgeCdromlibGetAppParam ("ncbi", "NCBI", "MEDIA", "", media, sizeof media);
1429 
1430     /* This is a work-around to provide backwards compatibility for old       */
1431     /* config files which do not specify MEDIA                                */
1432     if (media[0] == '\0')
1433     {
1434         StrCpy(media, "NCBI");
1435         SetSoleMedia();
1436     }
1437 
1438     m2 = media;
1439     StrCat(m2, "\n");
1440     done = FALSE;
1441 
1442     /* parse "MEDIA", looking for all data sources; note that we don't use */
1443     /* strtok(), because it's not re-entrant                               */
1444     while ((m1 = StringPBrk(m2, ",\n\r")) != NULL && !done)
1445     {
1446         if (*m1 == '\n' || *m1 == '\r' || *m1 == '\0')
1447             done = TRUE;
1448         *m1 = '\0';
1449         word = m2;
1450         m2 = m1 + 1;
1451         m2 += StringSpn(m2, " \t"); /* remove leading spaces and tabs from next word */
1452 
1453         mp = PreInitMedia(word);
1454         if (mp->media_type & media_mask)
1455         {
1456             if (initfunc != NULL)
1457             {
1458                 if (initfunc(word))
1459                 {
1460                     mp->in_use = TRUE;
1461                     mp->invalid = FALSE;
1462                     numProcessed++;
1463                 }
1464             }
1465             else {
1466                 mp->in_use = TRUE;
1467                 mp->invalid = FALSE;
1468                 numProcessed++;
1469             }
1470         }
1471         else {
1472             if (! mp->in_use)
1473                 mp->invalid = TRUE;
1474         }
1475     }
1476 
1477     return numProcessed;
1478 }
1479