IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Apr 17, 2006, 8:10:08 AM (20 years ago)
Author:
magnier
Message:

fixed up conflicts

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psModules/src/config/pmConfig.c

    r6418 r6873  
    33 *  @author PAP, IfA
    44 *
    5  *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
    6  *  @date $Date: 2006-02-10 02:43:19 $
     5 *  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
     6 *  @date $Date: 2006-04-17 18:10:08 $
    77 *
    88 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    1111#include <stdio.h>
    1212#include <string.h>
     13#include <unistd.h>
     14#include <assert.h>
     15#include <sys/types.h>
     16#include <sys/stat.h>
     17#include <glob.h>
    1318#include "pslib.h"
    1419#include "pmConfig.h"
    1520
    16 #define PS_SITE "PS_SITE"               // Name of the environment variable containing the site config file
    17 #define PS_DEFAULT_SITE "ipprc.config"  // Default site config file
     21#define PS_SITE "PS_SITE"         // Name of the environment variable containing the site config file
     22#define PS_DEFAULT_SITE ".ipprc"  // Default site config file
     23
     24static psArray *configPath = NULL;
     25
     26static void configFree(pmConfig *config)
     27{
     28    psFree(config->site);
     29    psFree(config->files);
     30    psFree(config->camera);
     31    psFree(config->recipes);
     32    psFree(config->arguments);
     33    psFree(config->database);
     34}
     35
     36pmConfig *pmConfigAlloc(void)
     37{
     38    pmConfig *config = psAlloc(sizeof(pmConfig));
     39    (void)psMemSetDeallocator(config, (psFreeFunc)configFree);
     40
     41    // Initialise
     42    config->site = NULL;
     43    config->camera = NULL;
     44    config->recipes = NULL;
     45    config->arguments = NULL;
     46    config->database = NULL;
     47
     48    // the file structure is used to carry pmFPAfiles
     49    config->files = psMetadataAlloc ();
     50    return config;
     51}
     52
     53void pmConfigDone(void)
     54{
     55    psFree(configPath);
     56}
     57
    1858
    1959/** readConfig
     
    2363 *
    2464 */
    25 static bool readConfig(
     65bool readConfig(
    2666    psMetadata **config,                // Config to output
    2767    const char *name,                   // Name of file
    2868    const char *description)            // Description of file
    2969{
     70    char *realName = NULL;
    3071    unsigned int numBadLines = 0;
     72    struct stat filestat;
    3173
    3274    psLogMsg(__func__, PS_LOG_INFO, "Loading %s configuration from file %s\n",
    3375             description, name);
    34     *config = psMetadataConfigParse(NULL, &numBadLines, name, true);
     76
     77    uid_t uid = getuid();
     78    gid_t gid = getgid();
     79
     80    // we try: name, path[0]/name, path[1]/name, ...
     81    // find the first existing entry in the path (starting with the bare name)
     82    realName = psStringCopy (name);
     83    psTrace (__func__, 5, "trying %s\n", realName);
     84
     85    int status = stat (realName, &filestat);
     86    if (status == 0) {
     87        if ((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR))
     88            goto found;
     89        if ((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP))
     90            goto found;
     91        if (filestat.st_mode & S_IROTH)
     92            goto found;
     93    }
     94    psFree (realName);
     95
     96    if (configPath == NULL) {
     97        psError(PS_ERR_IO, false, "Cannot find %s configuration file in path\n", description);
     98        return false;
     99    }
     100
     101    for (int i = 0; i < configPath->n; i++) {
     102        realName = psStringCopy (configPath->data[i]);
     103        psStringAppend (&realName, "/%s", name);
     104        psTrace (__func__, 5, "trying %s\n", realName);
     105
     106        status = stat (realName, &filestat);
     107        if (status == 0) {
     108            if ((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR))
     109                goto found;
     110            if ((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP))
     111                goto found;
     112            if (filestat.st_mode & S_IROTH)
     113                goto found;
     114        }
     115        psFree (realName);
     116    }
     117
     118    psError(PS_ERR_IO, false, "Cannot find %s configuration file in path\n", description);
     119    return false;
     120
     121found:
     122    *config = psMetadataConfigParse(NULL, &numBadLines, realName, true);
    35123    if (numBadLines > 0) {
    36124        psLogMsg(__func__, PS_LOG_WARN, "%d bad lines in %s configuration file (%s)\n",
    37                  description, name);
     125                 description, realName);
    38126    }
    39127    if (!*config) {
    40128        psError(PS_ERR_IO, false, "Unable to read %s configuration from %s\n",
    41                 description, name);
     129                description, realName);
     130        psFree (realName);
    42131        return false;
    43132    }
    44133
     134    psFree (realName);
    45135    return true;
    46136}
     
    57147 line.
    58148 *****************************************************************************/
    59 bool pmConfigRead(
    60     psMetadata **site,
    61     psMetadata **camera,
    62     psMetadata **recipe,
     149pmConfig *pmConfigRead(
    63150    int *argc,
    64     char **argv,
    65     const char *recipeName)
    66 {
    67     /* XXX: We need clarification on what is to be done if these arguments are
    68     NULL.
    69         PS_ASSERT_PTR_NON_NULL(site, false);
    70         PS_ASSERT_PTR_NON_NULL(*site, false);
    71         PS_ASSERT_PTR_NON_NULL(camera, false);
    72         PS_ASSERT_PTR_NON_NULL(*camera, false);
    73         PS_ASSERT_PTR_NON_NULL(recipe, false);
    74         PS_ASSERT_PTR_NON_NULL(*recipe, false);
    75         PS_ASSERT_INT_POSITIVE(*argc, false);
    76         PS_ASSERT_PTR_NON_NULL(argv, false);
    77     */
     151    char **argv)
     152{
     153    PS_ASSERT_INT_POSITIVE(*argc, false);
     154    PS_ASSERT_PTR_NON_NULL(argv, false);
     155
     156    pmConfig *config = pmConfigAlloc(); // The configuration, containing site, camera and recipes
     157
    78158    //
    79159    // The following section of code attempts to determine which file is
     
    97177                     "-site command-line switch provided without the required filename --- ignored.\n");
    98178        } else {
    99             siteName = argv[argNum];
     179            siteName = psStringCopy(argv[argNum]);
    100180            psArgumentRemove(argNum, argc, argv);
    101181        }
     
    106186    if (!siteName) {
    107187        siteName = getenv(PS_SITE);
     188        if (siteName) {
     189            siteName = psStringCopy (siteName);
     190        }
    108191    }
    109192
     
    111194    // Last chance is ~/.ipprc
    112195    //
    113     bool cleanupSiteName = false; // Do I have to psFree siteName?
    114196    if (!siteName) {
    115         siteName = psStringCopy(PS_DEFAULT_SITE);
    116         cleanupSiteName = true;
    117     }
    118 
    119     //
    120     // We have the connfiguration filename; now we read and parse the config
     197        char *home = getenv("HOME");
     198        siteName = psStringCopy(home);
     199        psStringAppend(&siteName, "/%s", PS_DEFAULT_SITE);
     200    }
     201
     202
     203    // We have the configuration filename; now we read and parse the config
    121204    // file and store in psMetadata struct site.
    122205    //
    123206
    124     if (!readConfig(site, siteName, "site")) {
    125         return false;
    126     }
    127     if (cleanupSiteName) {
    128         psFree(siteName);
    129     }
    130 
    131 
    132     //
    133     // Next, we do a similar thing for the recipe configuration file.  The
    134     // file is read and parsed into psMetadata struct "recipe".
    135     //
    136     //
    137     argNum = psArgumentGet(*argc, argv, "-recipe");
    138     if (argNum > 0) {
    139         psArgumentRemove(argNum, argc, argv);
    140         if (argNum >= *argc) {
    141             psLogMsg(__func__, PS_LOG_WARN,
    142                      "-recipe command-line switch provided without the required filename --- ignored.\n");
    143         } else {
    144             psArgumentRemove(argNum, argc, argv);
    145             readConfig(recipe, argv[argNum], "recipe");
    146         }
    147     }
    148     // Or, load the recipe from the camera file, if appropriate
    149     if (! *recipe && *camera && recipeName) {
    150         *recipe = pmConfigRecipeFromCamera(*camera, recipeName);
    151     }
    152 
    153 
    154     //
     207    if (!readConfig(&config->site, siteName, "site")) {
     208        psFree(config);
     209        return NULL;
     210    }
     211    psFree(siteName);
     212
     213    // define the config-file search path (configPath)
     214    if (configPath) {
     215        psFree(configPath);
     216        configPath = NULL;
     217    }
     218    char *path = psMetadataLookupStr(NULL, config->site, "PATH");
     219    if (path) {
     220        psList *list = psStringSplit(path, ":");
     221        configPath = psListToArray(list);
     222        psFree(list);
     223    }
     224
    155225    // Next, we do a similar thing for the camera configuration file.  The
    156226    // file is read and parsed into psMetadata struct "camera".
     
    164234        } else {
    165235            psArgumentRemove(argNum, argc, argv);
    166             readConfig(camera, argv[argNum], "camera");
    167         }
    168     } else {
    169         // XXX: Not sure is this is correct.
    170         *camera = NULL;
     236            readConfig(&config->camera, argv[argNum], "camera");
     237        }
     238    }
     239
     240    // Load the recipes from the camera file, if appropriate
     241    if (! config->recipes && config->camera) {
     242        pmConfigReadRecipes(config);
    171243    }
    172244
     
    183255    // with a call to psTimeInitialize.
    184256    //
    185     psString timeName = psMetadataLookupStr(&mdok, *site, "TIME");
     257    psString timeName = psMetadataLookupStr(&mdok, config->site, "TIME");
    186258    if (mdok && timeName) {
    187259        psTrace(__func__, 7, "Initialising psTime with file %s\n", timeName);
     
    195267    // with a call to psLogSetLevel().
    196268    //
    197     int logLevel = psMetadataLookupS32(&mdok, *site, "LOGLEVEL");
     269    int logLevel = psMetadataLookupS32(&mdok, config->site, "LOGLEVEL");
    198270    if (mdok && logLevel >= 0) {
    199271        psTrace(__func__, 7, "Setting log level to %d\n", logLevel);
     
    206278    // with a call to psLogSetFormat().
    207279    //
    208     psString logFormat = psMetadataLookupStr(&mdok, *site, "LOGFORMAT");
     280    psString logFormat = psMetadataLookupStr(&mdok, config->site, "LOGFORMAT");
    209281    if (mdok && logFormat) {
    210282        psTrace(__func__, 7, "Setting log format to %s\n", logFormat);
     
    218290    // XXX: This is not spec'ed in the SDRS.
    219291    //
    220     psString logDest = psMetadataLookupStr(&mdok, *site, "LOGDEST");
     292    psString logDest = psMetadataLookupStr(&mdok, config->site, "LOGDEST");
    221293    if (mdok && logDest) {
    222         // XXX: Only stdout is provided for now; this section should be
     294        // XXX: Only stdout and stderr are provided for now; this section should be
    223295        // expanded in the future to do files, and perhaps even sockets.
    224         if (strcasecmp(logDest, "STDOUT") != 0) {
    225             psLogMsg(__func__, PS_LOG_WARN, "Only STDOUT is currently supported as a log destination.\n");
     296        int logFD = STDIN_FILENO; // a known invalid value
     297        if (!strcasecmp(logDest, "STDOUT")) {
     298            logFD = STDOUT_FILENO;
     299        }
     300        if (!strcasecmp(logDest, "STDERR")) {
     301            logFD = STDERR_FILENO;
     302        }
     303        if (logFD == STDIN_FILENO) {
     304            psLogMsg(__func__, PS_LOG_WARN, "Only STDERR and STDOUT currently supported as a log destination.\n");
     305            logFD = STDERR_FILENO;
    226306        }
    227307        psTrace(__func__, 7, "Setting log destination to STDOUT.\n");
    228         // XXX: Use something other than "1"
    229         psLogSetDestination(1);
    230     }
    231 
     308        psLogSetDestination(logFD);
     309    }
    232310
    233311    //
     
    236314    // XXX: This is not spec'ed in the SDRS.
    237315    //
    238     psMetadata *trace = psMetadataLookupMD(&mdok, *site, "TRACE");
     316    psMetadata *trace = psMetadataLookupMD(&mdok, config->site, "TRACE");
    239317    if (mdok && trace) {
    240318        psMetadataIterator *traceIter = psMetadataIteratorAlloc(trace, PS_LIST_HEAD, NULL); // Iterator
     
    264342        psLogSetLevel(saveLogLevel);
    265343    }
    266     return(true);
    267 }
    268 
    269 bool pmConfigValidateCamera(
    270     const psMetadata *camera,
     344
     345    return config;
     346}
     347
     348
     349bool pmConfigValidateCameraFormat(
     350    const psMetadata *cameraFormat,
    271351    const psMetadata *header)
    272352{
    273     // Read the rule for that camera
     353    // Read the rule for that camera format
    274354    bool mdStatus = true;
    275     psMetadata *rule = psMetadataLookupMD(&mdStatus, camera, "RULE");
     355    psMetadata *rule = psMetadataLookupMD(&mdStatus, cameraFormat, "RULE");
    276356    if (! mdStatus || ! rule) {
    277357        psLogMsg(__func__, PS_LOG_WARN, "Unable to read rule for camera.\n");
     
    282362    psMetadataIterator *ruleIter = psMetadataIteratorAlloc(rule, PS_LIST_HEAD, NULL); // Rule iterator
    283363    psMetadataItem *ruleItem = NULL;    // Item from the metadata
    284     bool match = true;                  // Does it match?
    285     while ((ruleItem = psMetadataGetAndIncrement(ruleIter)) && match) {
     364    while ((ruleItem = psMetadataGetAndIncrement(ruleIter))) {
    286365        // Check for the existence of the rule
    287366        psMetadataItem *headerItem = psMetadataLookup((psMetadata*)header, ruleItem->name);
    288367        if (! headerItem || headerItem->type != ruleItem->type) {
    289             match = false;
     368            psFree(ruleIter);
     369            return false;
    290370        }
    291371
     
    297377            if (strncmp(ruleItem->data.V, headerItem->data.V,
    298378                        strlen(ruleItem->data.V)) != 0) {
    299                 match = false;
     379                psFree(ruleIter);
     380                return false;
    300381            }
    301382            break;
     
    305386                    ruleItem->data.S32, headerItem->data.S32);
    306387            if (ruleItem->data.S32 != headerItem->data.S32) {
    307                 match = false;
     388                psFree(ruleIter);
     389                return false;
    308390            }
    309391            break;
     
    312394                    ruleItem->data.F32, headerItem->data.F32);
    313395            if (ruleItem->data.F32 != headerItem->data.F32) {
    314                 match = false;
     396                psFree(ruleIter);
     397                return false;
    315398            }
    316399            break;
     
    319402                    ruleItem->data.F64, headerItem->data.F64);
    320403            if (ruleItem->data.F64 != headerItem->data.F64) {
    321                 match = false;
     404                psFree(ruleIter);
     405                return false;
    322406            }
    323407            break;
     
    329413
    330414    psFree(ruleIter);
    331 
    332     return match;
    333 }
    334 
    335 
    336 
    337 // Work out what camera we have, based on the FITS header and a set of
    338 // rules specified in the IPP configuration; return the camera configuration
    339 psMetadata *pmConfigCameraFromHeader(
    340     const psMetadata *ipprc,            // The IPP configuration
    341     const psMetadata *header)           // The FITS header
    342 {
    343     bool mdStatus = false;  // Metadata lookup status
    344     psMetadata *cameras = psMetadataLookupMD(&mdStatus, ipprc, "CAMERAS");
    345     if (! mdStatus) {
    346         psError(PS_ERR_IO, false, "Unable to find CAMERAS in the configuration.\n");
    347         return NULL;
    348     }
    349     psMetadata *winner = NULL;       // The camera configuration whose rule first matches
    350     //  the supplied header
    351     // Iterate over the cameras
    352     psMetadataIterator *iterator = psMetadataIteratorAlloc(cameras, PS_LIST_HEAD, NULL);
    353     psMetadataItem *cameraItem = NULL; // Item from the metadata
    354 
    355     while ((cameraItem = psMetadataGetAndIncrement(iterator))) {
    356         // Open the camera information
    357         psTrace(__func__, 3, "Inspecting camera %s (%s)\n", cameraItem->name,
    358                 cameraItem->comment);
    359         psMetadata *camera = NULL; // The camera metadata
    360         if (cameraItem->type == PS_DATA_METADATA) {
    361             camera = psMemIncrRefCounter(cameraItem->data.md);
    362         } else if (cameraItem->type == PS_DATA_STRING) {
    363             psTrace(__func__, 5, "Reading camera configuration for %s...\n", cameraItem->name);
    364             unsigned int badLines = 0;  // Number of bad lines in reading camera configuration
    365             camera = psMetadataConfigParse(NULL, &badLines, cameraItem->data.V, true);
     415    return true;
     416}
     417
     418
     419static bool formatFromHeader(psMetadata **format, // Format to return
     420                             psMetadata *camera, // Camera configuration
     421                             const psMetadata *header, // FITS header
     422                             const char *cameraName // Name of camera
     423                            )
     424{
     425    psMetadata *testFormat;
     426
     427    assert(format);
     428    assert(camera);
     429    assert(header);
     430
     431    bool result = false;                // Did we find the first match?
     432
     433    // Read the list of formats
     434    bool mdok = true;                   // Status of MD lookup
     435    psMetadata *formats = psMetadataLookupMD(&mdok, camera, "FORMATS"); // List of formats
     436    if (!mdok || !formats) {
     437        psLogMsg(__func__, PS_LOG_WARN, "Unable to find list of FORMATS in camera %s --- ignored\n",
     438                 cameraName);
     439        return false;
     440    }
     441    // Iterate over the formats
     442    psMetadataIterator *formatsIter = psMetadataIteratorAlloc(formats, PS_LIST_HEAD, NULL);
     443    psMetadataItem *formatsItem = NULL; // Item from formats
     444    while ((formatsItem = psMetadataGetAndIncrement(formatsIter))) {
     445        if (formatsItem->type != PS_DATA_STRING) {
     446            psLogMsg(__func__, PS_LOG_WARN, "In camera %s, camera format %s is not of type STR --- "
     447                     "ignored.\n", cameraName, formatsItem->name);
     448            continue;
     449        }
     450        psTrace(__func__, 5, "Reading camera format for %s...\n", formatsItem->name);
     451        // unsigned int badLines = 0;  // Number of bad lines in reading camera configuration
     452        // Format to test against what we've got
     453
     454        if (!readConfig(&testFormat, formatsItem->data.V, formatsItem->name)) {
     455            psLogMsg(__func__, PS_LOG_WARN, "trouble reading reading camera format %s\n", formatsItem->name);
     456            psFree(testFormat);
     457            continue;
     458        }
     459
     460        # if (0)
     461            psMetadata *testFormat = psMetadataConfigParse(NULL, &badLines, formatsItem->data.V, true);
     462        if (badLines > 0) {
     463            psLogMsg(__func__, PS_LOG_WARN, "%d bad lines encountered while reading camera"
     464                     "format %s\n", badLines, formatsItem->name);
     465        }
     466        # endif
     467
     468        if (pmConfigValidateCameraFormat(testFormat, header)) {
     469            if (!*format) {
     470                psLogMsg(__func__, PS_LOG_INFO, "Camera %s, format %s matches header.\n", cameraName,
     471                         formatsItem->name);
     472                *format = psMemIncrRefCounter(testFormat);
     473                result = true;
     474            } else {
     475                psLogMsg(__func__, PS_LOG_WARN, "Camera %s, format %s also matches header --- ignored.\n",
     476                         cameraName, formatsItem->name);
     477            }
     478        }
     479        psFree(testFormat);
     480    }
     481    psFree(formatsIter);
     482
     483    return result;
     484}
     485
     486// Work out what camera we have, based on the FITS header and a set of rules specified in the IPP
     487// configuration; return the camera configuration and format
     488psMetadata *pmConfigCameraFormatFromHeader(
     489    pmConfig *config,                   // The configuration
     490    const psMetadata *header           // The FITS header
     491)
     492{
     493    psMetadata *format = NULL;          // The winning format
     494    bool mdok = false;                  // Metadata lookup status
     495    psMetadata *testCamera = NULL;
     496
     497    // If we don't know what sort of camera we have, we try all that we know
     498    if (! config->camera) {
     499        psMetadata *cameras = psMetadataLookupMD(&mdok, config->site, "CAMERAS");
     500        if (! mdok) {
     501            psError(PS_ERR_IO, false, "Unable to find CAMERAS in the configuration.\n");
     502            return false;
     503        }
     504
     505        // Iterate over the cameras
     506        psMetadataIterator *camerasIter = psMetadataIteratorAlloc(cameras, PS_LIST_HEAD, NULL);
     507        psMetadataItem *camerasItem = NULL; // Item from the metadata
     508        while ((camerasItem = psMetadataGetAndIncrement(camerasIter))) {
     509            // Open the camera information
     510            psTrace(__func__, 3, "Inspecting camera %s (%s)\n", camerasItem->name, camerasItem->comment);
     511            if (camerasItem->type != PS_DATA_STRING) {
     512                psLogMsg(__func__, PS_LOG_WARN, "Camera configuration for %s in CAMERAS is not of type STR "
     513                         "--- ignored.\n", camerasItem->name);
     514                continue;
     515            }
     516
     517            psTrace(__func__, 5, "Reading camera configuration for %s...\n", camerasItem->name);
     518            // unsigned int badLines = 0;  // Number of bad lines in reading camera configuration
     519            // Camera to test against what we've got:
     520
     521            if (!readConfig(&testCamera, camerasItem->data.V, camerasItem->name)) {
     522                psLogMsg(__func__, PS_LOG_WARN, "trouble reading reading camera configuration %s\n", camerasItem->name);
     523                psFree(testCamera);
     524                continue;
     525            }
     526
     527            # if (0)
     528                psMetadata *testCamera = psMetadataConfigParse(NULL, &badLines, camerasItem->data.V, true);
    366529            if (badLines > 0) {
    367530                psLogMsg(__func__, PS_LOG_WARN, "%d bad lines encountered while reading camera"
    368                          "configuration %s\n", badLines, cameraItem->name);
    369             }
    370         }
    371 
    372         if (! camera) {
    373             psLogMsg(__func__, PS_LOG_WARN, "Unable to interpret camera configuration for %s (%s)\n",
    374                      cameraItem->name, cameraItem->comment);
    375             continue;
    376         }
    377 
    378         if (pmConfigValidateCamera(camera, header)) {
    379             if (! winner) {
    380                 // This is the first match
    381                 winner = psMemIncrRefCounter(camera);
    382                 psLogMsg(__func__, PS_LOG_INFO, "FITS header matches camera %s\n",
    383                          cameraItem->name);
    384             } else {
    385                 // We have a duplicate match
    386                 psLogMsg(__func__, PS_LOG_WARN, "Additional camera found that matches the rules: %s\n",
    387                          cameraItem->name);
    388             }
    389         } // Done inspecting the camera
    390 
    391         psFree(camera);
    392 
    393     } // Done looking at all cameras
    394     if (! winner) {
    395         psError(PS_ERR_IO, true, "Unable to find an camera that matches input FITS header!\n");
    396     }
    397 
    398     psFree(iterator);
    399     return winner;
    400 }
    401 
    402 psMetadata *pmConfigRecipeFromCamera(
    403     const psMetadata *camera,
    404     const char *recipeName)
    405 {
    406     PS_ASSERT_PTR_NON_NULL(camera, false);
    407     PS_ASSERT_PTR_NON_NULL(recipeName, false);
    408 
    409     psMetadata *recipe = NULL;          // Recipe to read
     531                         "configuration %s\n", badLines, camerasItem->name);
     532            }
     533            # endif
     534
     535            if (! testCamera) {
     536                psLogMsg(__func__, PS_LOG_WARN, "Unable to interpret camera configuration for %s (%s) --- "
     537                         "ignored\n", camerasItem->name, camerasItem->comment);
     538                continue;
     539            }
     540
     541            if (formatFromHeader(&format, testCamera, header, camerasItem->name)) {
     542                config->camera = psMemIncrRefCounter(testCamera);
     543            }
     544            psFree(testCamera);
     545        } // Done looking at all cameras
     546        psFree(camerasIter);
     547
     548        if (! config->camera) {
     549            psError(PS_ERR_IO, true, "Unable to find a camera that matches input FITS header!\n");
     550            return NULL;
     551        }
     552
     553        // Now we have the camera, we can read the recipes
     554        if (!config->recipes) {
     555            pmConfigReadRecipes(config);
     556        }
     557
     558        return format;
     559    }
     560
     561    // Otherwise, try the specific camera
     562    if (! formatFromHeader(&format, config->camera, header, "specified camera")) {
     563        psError(PS_ERR_IO, true, "Unable to find a format with the specified camera that matches the "
     564                "given header.\n");
     565        return NULL;
     566    }
     567    return format;
     568}
     569
     570bool pmConfigReadRecipes(
     571    pmConfig *config
     572)
     573{
     574    PS_ASSERT_PTR_NON_NULL(config, false);
     575    PS_ASSERT_PTR_NON_NULL(config->camera, false);
     576
     577    if (!config->recipes) {
     578        config->recipes = psMetadataAlloc();
     579    }
     580
    410581    bool mdok = true;                   // Status of MD lookup
    411     psMetadata *recipes = psMetadataLookupMD(&mdok, camera, "RECIPES"); // The list of recipes
     582    psMetadata *recipes = psMetadataLookupMD(&mdok, config->camera, "RECIPES"); // The list of recipes
    412583    if (! mdok || ! recipes) {
    413584        psLogMsg(__func__, PS_LOG_WARN, "RECIPES in the camera configuration file is not of type METADATA\n");
    414     } else {
    415         psString recipeFileName = psMetadataLookupStr(&mdok, recipes, recipeName);
    416         (void)readConfig(&recipe, recipeFileName, "recipe");
    417     }
    418 
    419     return recipe;
     585        return false;
     586    }
     587    // Go through the recipes and load each one
     588    psMetadataIterator *recipesIter = psMetadataIteratorAlloc(recipes, PS_LIST_HEAD, NULL); // Iterator
     589    psMetadataItem *recipesItem = NULL; // Item from iteration
     590    while ((recipesItem = psMetadataGetAndIncrement(recipesIter))) {
     591        if (recipesItem->type != PS_DATA_STRING) {
     592            psLogMsg(__func__, PS_LOG_WARN, "Filename for recipe %s isn't of type STR --- ignored.\n",
     593                     recipesItem->name);
     594            continue;
     595        }
     596
     597        psMetadata *recipe = NULL;      // Recipe from file
     598        if (readConfig(&recipe, recipesItem->data.V, "recipe")) {
     599            psMetadataAdd(config->recipes, PS_LIST_TAIL, recipesItem->name,
     600                          PS_DATA_METADATA | PS_META_REPLACE, recipesItem->comment, recipe);
     601        }
     602        psFree(recipe);                 // Drop reference
     603    }
     604    psFree(recipesIter);
     605
     606    return true;
    420607}
    421608
     
    423610pmConfigDB(*site)
    424611 
     612XXX: this should allow the option of having NO database server, if chosen by config
    425613XXX: What should we use for the Database namespace in the call to psDBInit()?
    426614This is currently NULL.
    427615 *****************************************************************************/
    428616
    429 #ifdef OMIT_PSDB
    430 psDB *pmConfigDB(psMetadata *site)
    431 {
    432     psError(PS_ERR_UNKNOWN, true, "pslib was built without psDB support");
    433     return NULL;
    434 }
    435 #else
    436617psDB *pmConfigDB(
    437618    psMetadata *site)
     
    442623    psBool mdStatus03 = false;
    443624
     625    // XXX leaky strings
    444626    psString dbServer = psMetadataLookupStr(&mdStatus01, site, "DBSERVER");
    445627    psString dbUsername = psMetadataLookupStr(&mdStatus02, site, "DBUSER");
    446628    psString dbPassword = psMetadataLookupStr(&mdStatus03, site, "DBPASSWORD");
    447629    psString dbName = psMetadataLookupStr(&mdStatus01, site, "DBNAME");
    448 
    449630    if (!(mdStatus01 & mdStatus02 & mdStatus03)) {
    450631        psLogMsg(__func__, PS_LOG_WARN, "Could not determine database server name, userID, and password from site metadata.\n");
    451         return NULL;
    452     }
    453 
    454 
    455 
    456     psDB *dbh = psDBInit(dbServer, dbUsername, dbPassword, dbName);
    457     psFree(dbServer);
    458     psFree(dbUsername);
    459     psFree(dbPassword);
    460     psFree(dbName);
    461 
    462     if (!dbh) {
    463         psError(PS_ERR_UNKNOWN, false, "database connection failed");
    464     }
    465 
    466     return dbh;
    467 }
    468 #endif
     632        return(NULL);
     633    }
     634
     635    return(psDBInit(dbServer, dbUsername, dbPassword, dbName));
     636}
     637
     638
     639bool pmConfigConformHeader(psMetadata *header, // Header to conform
     640                           const psMetadata *format // Camera format
     641                          )
     642{
     643    bool mdok = true;                   // Status of MD lookup
     644    psMetadata *rules = psMetadataLookupMD(&mdok, format, "RULE"); // How to identify this format
     645    if (!mdok || !rules) {
     646        psError(PS_ERR_IO, false, "Unable to find RULE in camer format.\n");
     647        return false;
     648    }
     649
     650    psMetadataIterator *rulesIter = psMetadataIteratorAlloc(rules, PS_LIST_HEAD, NULL); // Iterator for rules
     651    psMetadataItem *rulesItem = NULL;   // Item from iteration
     652    while ((rulesItem = psMetadataGetAndIncrement(rulesIter))) {
     653        psMetadataItem *newItem = psMetadataItemCopy(rulesItem); // Copy of item
     654        psMetadataAddItem(header, newItem, PS_LIST_TAIL, PS_META_REPLACE);
     655        psFree(newItem);                // Drop reference
     656    }
     657    psFree(rulesIter);
     658
     659    return true;
     660}
     661
     662// given the 'file' and 'list' words, find the arguments associated with these words
     663// and interpret them as lists of files.  return an array of the resulting filenames.
     664psArray *pmConfigFileSets (int *argc, char **argv, char *file, char *list)
     665{
     666
     667    int Narg;
     668
     669    // we load all input files onto a psArray, to be parsed later
     670    psArray *input = psArrayAlloc (16);
     671    input->n = 0;
     672
     673    // load the list of filenames the supplied file (may be a glob: "file*.fits")
     674    if ((Narg = psArgumentGet (*argc, argv, file))) {
     675        glob_t globList;
     676        psArgumentRemove (Narg, argc, argv);
     677        globList.gl_offs = 0;
     678        glob (argv[Narg], 0, NULL, &globList);
     679        for (int i = 0; i < globList.gl_pathc; i++) {
     680            char *filename = psStringCopy (globList.gl_pathv[i]);
     681            psArrayAdd (input, 16, filename);
     682            psFree (filename);
     683        }
     684        psArgumentRemove (Narg, argc, argv);
     685    }
     686
     687    // load the list from the supplied text file
     688    if ((Narg = psArgumentGet (*argc, argv, list))) {
     689        int nItems;
     690        char line[1024]; // XXX limits the list lines to 1024 chars
     691        char word[1024];
     692        char *filename;
     693
     694        psArgumentRemove (Narg, argc, argv);
     695        FILE *f = fopen (argv[Narg], "r");
     696        if (f == NULL) {
     697            psAbort ("psphot", "unable to open specified list file");
     698        }
     699        while (fgets (line, 1024, f) != NULL) {
     700            nItems = sscanf (line, "%s", word);
     701            switch (nItems) {
     702            case 0:
     703                break;
     704            case 1:
     705                filename = psStringCopy (word);
     706                psArrayAdd (input, 16, filename);
     707                psFree (filename);
     708                break;
     709            default:
     710                // rigid format, no comments allowed?
     711                psAbort ("pmConfig", "error parsing input list file");
     712                break;
     713            }
     714        }
     715        psArgumentRemove (Narg, argc, argv);
     716    }
     717
     718    return input;
     719}
     720
     721bool pmConfigFileSetsMD (psMetadata *metadata, int *argc, char **argv, char *name, char *file, char *list)
     722{
     723
     724    psArray *files = pmConfigFileSets (argc, argv, file, list);
     725    if (files->n == 0) {
     726        psFree (files);
     727        return false;
     728    }
     729
     730    psMetadataAddPtr (metadata, PS_LIST_TAIL, name,  PS_DATA_ARRAY, "", files);
     731    psFree (files);
     732    return true;
     733}
Note: See TracChangeset for help on using the changeset viewer.