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