There's an ongoing project to bring some kind of path selection
authorRichard Levitte <levitte@openssl.org>
Mon, 15 Jul 2002 15:35:40 +0000 (15:35 +0000)
committerRichard Levitte <levitte@openssl.org>
Mon, 15 Jul 2002 15:35:40 +0000 (15:35 +0000)
mechanism to the ENGINE framework.  This means there there are going
to be new functionality for the DSO part, and ultimately some way of
merging two file specifications together.

This commit places the merging code into the repository.  It's
currently not used anywhere, and hasn't been tested at all.  It may be
full of errors, including syntactical ones.  Those will be fixed as
promptly as possible.

crypto/dso/dso.h
crypto/dso/dso_dl.c
crypto/dso/dso_dlfcn.c
crypto/dso/dso_err.c
crypto/dso/dso_lib.c
crypto/dso/dso_vms.c
crypto/dso/dso_win32.c

index aa721f7febb603ab5eebb94f1182bf79cda53715..2cf6e1ae1270d044d6c41be505526ada6f2b60cb 100644 (file)
@@ -1,4 +1,4 @@
-/* dso.h */
+/* dso.h -*- mode:C; c-file-style: "eay" -*- */
 /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
  * project 2000.
  */
@@ -107,6 +107,22 @@ typedef struct dso_st DSO;
  * condition) or a newly allocated string containing the transformed form that
  * the caller will need to free with OPENSSL_free() when done. */
 typedef char* (*DSO_NAME_CONVERTER_FUNC)(DSO *, const char *);
+/* The function prototype used for method functions (or caller-provided
+ * callbacks) that merge two file specifications. They are passed a
+ * DSO structure pointer (or NULL if they are to be used independantly of
+ * a DSO object) and two file specifications to merge. They should
+ * either return NULL (if there is an error condition) or a newly allocated
+ * string containing the result of merging that the caller will need
+ * to free with OPENSSL_free() when done.
+ * Here, merging means that bits and pieces are taken from each of the
+ * file specifications and added together in whatever fashion that is
+ * sensible for the DSO method in question.  The only rule that really
+ * applies is that if the two specification contain pieces of the same
+ * type, the copy from the string string takes priority.  One could see
+ * it as the first specification is the one given by the user and the
+ * second being a bunch of defaults to add on if they're missing in the
+ * first. */
+typedef char* (*DSO_MERGER_FUNC)(DSO *, const char *, const char *);
 
 typedef struct dso_meth_st
        {
@@ -140,6 +156,9 @@ typedef struct dso_meth_st
        /* The default DSO_METHOD-specific function for converting filenames to
         * a canonical native form. */
        DSO_NAME_CONVERTER_FUNC dso_name_converter;
+       /* The default DSO_METHOD-specific function for converting filenames to
+        * a canonical native form. */
+       DSO_MERGER_FUNC dso_merger;
 
        /* [De]Initialisation handlers. */
        int (*init)(DSO *dso);
@@ -164,9 +183,13 @@ struct dso_st
         * don't touch meth_data! */
        CRYPTO_EX_DATA ex_data;
        /* If this callback function pointer is set to non-NULL, then it will
-        * be used on DSO_load() in place of meth->dso_name_converter. NB: This
+        * be used in DSO_load() in place of meth->dso_name_converter. NB: This
         * should normally set using DSO_set_name_converter(). */
        DSO_NAME_CONVERTER_FUNC name_converter;
+       /* If this callback function pointer is set to non-NULL, then it will
+        * be used in DSO_load() in place of meth->dso_merger. NB: This
+        * should normally set using DSO_set_merger(). */
+       DSO_MERGER_FUNC merger;
        /* This is populated with (a copy of) the platform-independant
         * filename used for this DSO. */
        char *filename;
@@ -209,6 +232,11 @@ int        DSO_set_filename(DSO *dso, const char *filename);
  * caller-created DSO_METHODs can do the same thing. A non-NULL return value
  * will need to be OPENSSL_free()'d. */
 char   *DSO_convert_filename(DSO *dso, const char *filename);
+/* This function will invoke the DSO's merger callback to merge two file
+ * specifications, or if the callback isn't set it will instead use the
+ * DSO_METHOD's merger.  A non-NULL return value will need to be
+ * OPENSSL_free()'d. */
+char   *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2);
 /* If the DSO is currently loaded, this returns the filename that it was loaded
  * under, otherwise it returns NULL. So it is also useful as a test as to
  * whether the DSO is currently loaded. NB: This will not necessarily return
@@ -273,11 +301,13 @@ void ERR_load_DSO_strings(void);
 #define DSO_F_DLFCN_BIND_FUNC                           100
 #define DSO_F_DLFCN_BIND_VAR                            101
 #define DSO_F_DLFCN_LOAD                                102
+#define DSO_F_DLFCN_MERGER                              130
 #define DSO_F_DLFCN_NAME_CONVERTER                      123
 #define DSO_F_DLFCN_UNLOAD                              103
 #define DSO_F_DL_BIND_FUNC                              104
 #define DSO_F_DL_BIND_VAR                               105
 #define DSO_F_DL_LOAD                                   106
+#define DSO_F_DL_MERGER                                         131
 #define DSO_F_DL_NAME_CONVERTER                                 124
 #define DSO_F_DL_UNLOAD                                         107
 #define DSO_F_DSO_BIND_FUNC                             108
@@ -288,24 +318,30 @@ void ERR_load_DSO_strings(void);
 #define DSO_F_DSO_GET_FILENAME                          127
 #define DSO_F_DSO_GET_LOADED_FILENAME                   128
 #define DSO_F_DSO_LOAD                                  112
+#define DSO_F_DSO_MERGE                                         132
 #define DSO_F_DSO_NEW_METHOD                            113
 #define DSO_F_DSO_SET_FILENAME                          129
 #define DSO_F_DSO_SET_NAME_CONVERTER                    122
 #define DSO_F_DSO_UP_REF                                114
 #define DSO_F_VMS_BIND_VAR                              115
 #define DSO_F_VMS_LOAD                                  116
+#define DSO_F_VMS_MERGER                                133
 #define DSO_F_VMS_UNLOAD                                117
 #define DSO_F_WIN32_BIND_FUNC                           118
 #define DSO_F_WIN32_BIND_VAR                            119
 #define DSO_F_WIN32_LOAD                                120
+#define DSO_F_WIN32_MERGER                              134
 #define DSO_F_WIN32_NAME_CONVERTER                      125
 #define DSO_F_WIN32_UNLOAD                              121
 
 /* Reason codes. */
 #define DSO_R_CTRL_FAILED                               100
 #define DSO_R_DSO_ALREADY_LOADED                        110
+#define DSO_R_EMPTY_FILE_STRUCTURE                      113
+#define DSO_R_FAILURE                                   114
 #define DSO_R_FILENAME_TOO_BIG                          101
 #define DSO_R_FINISH_FAILED                             102
+#define DSO_R_INCORRECT_FILE_SYNTAX                     115
 #define DSO_R_LOAD_FAILED                               103
 #define DSO_R_NAME_TRANSLATION_FAILED                   109
 #define DSO_R_NO_FILENAME                               111
index 195717e9935b2b6d9c5b8e7a106b66bed8ad96d7..32a8d41bf74986ac8ee584908e0eeeb1575be475 100644 (file)
@@ -1,4 +1,4 @@
-/* dso_dl.c */
+/* dso_dl.c -*- mode:C; c-file-style: "eay" -*- */
 /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
  * project 2000.
  */
@@ -84,6 +84,7 @@ static int dl_finish(DSO *dso);
 static int dl_ctrl(DSO *dso, int cmd, long larg, void *parg);
 #endif
 static char *dl_name_converter(DSO *dso, const char *filename);
+static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2);
 
 static DSO_METHOD dso_meth_dl = {
        "OpenSSL 'dl' shared library method",
@@ -98,6 +99,7 @@ static DSO_METHOD dso_meth_dl = {
 #endif
        NULL, /* ctrl */
        dl_name_converter,
+       dl_merger,
        NULL, /* init */
        NULL  /* finish */
        };
@@ -238,6 +240,72 @@ static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname)
        return((DSO_FUNC_TYPE)sym);
        }
 
+static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2)
+       {
+       char *merged;
+
+       if(!filespec1 && !filespec2)
+               {
+               DSOerr(DSO_F_DL_MERGER,
+                               ERR_R_PASSED_NULL_PARAMETER);
+               return(NULL);
+               }
+       /* If the first file specification is a rooted path, it rules.
+          same goes if the second file specification is missing. */
+       if (!filespec2 || filespec1[0] == '/')
+               {
+               merged = OPENSSL_malloc(strlen(filespec1) + 1);
+               if(!merged)
+                       {
+                       DSOerr(DSO_F_DL_MERGER,
+                               ERR_R_MALLOC_FAILURE);
+                       return(NULL);
+                       }
+               strcpy(merged, filespec1);
+               }
+       /* If the first file specification is missing, the second one rules. */
+       else if (!filespec1)
+               {
+               merged = OPENSSL_malloc(strlen(filespec2) + 1);
+               if(!merged)
+                       {
+                       DSOerr(DSO_F_DL_MERGER,
+                               ERR_R_MALLOC_FAILURE);
+                       return(NULL);
+                       }
+               strcpy(merged, filespec2);
+               }
+       else
+               /* This part isn't as trivial as it looks.  It assumes that
+                  the second file specification really is a directory, and
+                  makes no checks whatsoever.  Therefore, the result becomes
+                  the concatenation of filespec2 followed by a slash followed
+                  by filespec1. */
+               {
+               int spec2len, len;
+
+               spec2len = (filespec2 ? strlen(filespec2) : 0);
+               len = spec2len + (filespec1 ? strlen(filespec1) : 0);
+
+               if(filespec2 && filespec2[spec2len - 1] == '/')
+                       {
+                       spec2len--;
+                       len--;
+                       }
+               merged = OPENSSL_malloc(len + 2);
+               if(!merged)
+                       {
+                       DSOerr(DSO_F_DL_MERGER,
+                               ERR_R_MALLOC_FAILURE);
+                       return(NULL);
+                       }
+               strcpy(merged, filespec2);
+               merged[spec2len] = '/';
+               strcpy(&merged[spec2len + 1], filespec1);
+               }
+       return(merged);
+       }
+
 /* This function is identical to the one in dso_dlfcn.c, but as it is highly
  * unlikely that both the "dl" *and* "dlfcn" variants are being compiled at the
  * same time, there's no great duplicating the code. Figuring out an elegant 
index 906b4703de71c4f42a210f8706b17a86118cfb83..de88b2fd16d033da6795271e10fe255de4ee6804 100644 (file)
@@ -1,4 +1,4 @@
-/* dso_dlfcn.c */
+/* dso_dlfcn.c -*- mode:C; c-file-style: "eay" -*- */
 /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
  * project 2000.
  */
@@ -85,6 +85,8 @@ static int dlfcn_finish(DSO *dso);
 static long dlfcn_ctrl(DSO *dso, int cmd, long larg, void *parg);
 #endif
 static char *dlfcn_name_converter(DSO *dso, const char *filename);
+static char *dlfcn_merger(DSO *dso, const char *filespec1,
+       const char *filespec2);
 
 static DSO_METHOD dso_meth_dlfcn = {
        "OpenSSL 'dlfcn' shared library method",
@@ -99,6 +101,7 @@ static DSO_METHOD dso_meth_dlfcn = {
 #endif
        NULL, /* ctrl */
        dlfcn_name_converter,
+       dlfcn_merger,
        NULL, /* init */
        NULL  /* finish */
        };
@@ -252,6 +255,73 @@ static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname)
        return(sym);
        }
 
+static char *dlfcn_merger(DSO *dso, const char *filespec1,
+       const char *filespec2)
+       {
+       char *merged;
+
+       if(!filespec1 && !filespec2)
+               {
+               DSOerr(DSO_F_DLFCN_MERGER,
+                               ERR_R_PASSED_NULL_PARAMETER);
+               return(NULL);
+               }
+       /* If the first file specification is a rooted path, it rules.
+          same goes if the second file specification is missing. */
+       if (!filespec2 || filespec1[0] == '/')
+               {
+               merged = OPENSSL_malloc(strlen(filespec1) + 1);
+               if(!merged)
+                       {
+                       DSOerr(DSO_F_DLFCN_MERGER,
+                               ERR_R_MALLOC_FAILURE);
+                       return(NULL);
+                       }
+               strcpy(merged, filespec1);
+               }
+       /* If the first file specification is missing, the second one rules. */
+       else if (!filespec1)
+               {
+               merged = OPENSSL_malloc(strlen(filespec2) + 1);
+               if(!merged)
+                       {
+                       DSOerr(DSO_F_DLFCN_MERGER,
+                               ERR_R_MALLOC_FAILURE);
+                       return(NULL);
+                       }
+               strcpy(merged, filespec2);
+               }
+       else
+               /* This part isn't as trivial as it looks.  It assumes that
+                  the second file specification really is a directory, and
+                  makes no checks whatsoever.  Therefore, the result becomes
+                  the concatenation of filespec2 followed by a slash followed
+                  by filespec1. */
+               {
+               int spec2len, len;
+
+               spec2len = (filespec2 ? strlen(filespec2) : 0);
+               len = spec2len + (filespec1 ? strlen(filespec1) : 0);
+
+               if(filespec2 && filespec2[spec2len - 1] == '/')
+                       {
+                       spec2len--;
+                       len--;
+                       }
+               merged = OPENSSL_malloc(len + 2);
+               if(!merged)
+                       {
+                       DSOerr(DSO_F_DLFCN_MERGER,
+                               ERR_R_MALLOC_FAILURE);
+                       return(NULL);
+                       }
+               strcpy(merged, filespec2);
+               merged[spec2len] = '/';
+               strcpy(&merged[spec2len + 1], filespec1);
+               }
+       return(merged);
+       }
+
 static char *dlfcn_name_converter(DSO *dso, const char *filename)
        {
        char *translated;
index cf452de1aa0657b6565f134905d070fabcd7e383..23ccfc00c567623e5a5616c3ab431c469af0ff9f 100644 (file)
@@ -1,6 +1,6 @@
 /* crypto/dso/dso_err.c */
 /* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2002 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -69,11 +69,13 @@ static ERR_STRING_DATA DSO_str_functs[]=
 {ERR_PACK(0,DSO_F_DLFCN_BIND_FUNC,0),  "DLFCN_BIND_FUNC"},
 {ERR_PACK(0,DSO_F_DLFCN_BIND_VAR,0),   "DLFCN_BIND_VAR"},
 {ERR_PACK(0,DSO_F_DLFCN_LOAD,0),       "DLFCN_LOAD"},
+{ERR_PACK(0,DSO_F_DLFCN_MERGER,0),     "DLFCN_MERGER"},
 {ERR_PACK(0,DSO_F_DLFCN_NAME_CONVERTER,0),     "DLFCN_NAME_CONVERTER"},
 {ERR_PACK(0,DSO_F_DLFCN_UNLOAD,0),     "DLFCN_UNLOAD"},
 {ERR_PACK(0,DSO_F_DL_BIND_FUNC,0),     "DL_BIND_FUNC"},
 {ERR_PACK(0,DSO_F_DL_BIND_VAR,0),      "DL_BIND_VAR"},
 {ERR_PACK(0,DSO_F_DL_LOAD,0),  "DL_LOAD"},
+{ERR_PACK(0,DSO_F_DL_MERGER,0),        "DL_MERGER"},
 {ERR_PACK(0,DSO_F_DL_NAME_CONVERTER,0),        "DL_NAME_CONVERTER"},
 {ERR_PACK(0,DSO_F_DL_UNLOAD,0),        "DL_UNLOAD"},
 {ERR_PACK(0,DSO_F_DSO_BIND_FUNC,0),    "DSO_bind_func"},
@@ -84,16 +86,19 @@ static ERR_STRING_DATA DSO_str_functs[]=
 {ERR_PACK(0,DSO_F_DSO_GET_FILENAME,0), "DSO_get_filename"},
 {ERR_PACK(0,DSO_F_DSO_GET_LOADED_FILENAME,0),  "DSO_get_loaded_filename"},
 {ERR_PACK(0,DSO_F_DSO_LOAD,0), "DSO_load"},
+{ERR_PACK(0,DSO_F_DSO_MERGE,0),        "DSO_merge"},
 {ERR_PACK(0,DSO_F_DSO_NEW_METHOD,0),   "DSO_new_method"},
 {ERR_PACK(0,DSO_F_DSO_SET_FILENAME,0), "DSO_set_filename"},
 {ERR_PACK(0,DSO_F_DSO_SET_NAME_CONVERTER,0),   "DSO_set_name_converter"},
 {ERR_PACK(0,DSO_F_DSO_UP_REF,0),       "DSO_up_ref"},
 {ERR_PACK(0,DSO_F_VMS_BIND_VAR,0),     "VMS_BIND_VAR"},
 {ERR_PACK(0,DSO_F_VMS_LOAD,0), "VMS_LOAD"},
+{ERR_PACK(0,DSO_F_VMS_MERGER,0),       "VMS_MERGER"},
 {ERR_PACK(0,DSO_F_VMS_UNLOAD,0),       "VMS_UNLOAD"},
 {ERR_PACK(0,DSO_F_WIN32_BIND_FUNC,0),  "WIN32_BIND_FUNC"},
 {ERR_PACK(0,DSO_F_WIN32_BIND_VAR,0),   "WIN32_BIND_VAR"},
 {ERR_PACK(0,DSO_F_WIN32_LOAD,0),       "WIN32_LOAD"},
+{ERR_PACK(0,DSO_F_WIN32_MERGER,0),     "WIN32_MERGER"},
 {ERR_PACK(0,DSO_F_WIN32_NAME_CONVERTER,0),     "WIN32_NAME_CONVERTER"},
 {ERR_PACK(0,DSO_F_WIN32_UNLOAD,0),     "WIN32_UNLOAD"},
 {0,NULL}
@@ -103,8 +108,11 @@ static ERR_STRING_DATA DSO_str_reasons[]=
        {
 {DSO_R_CTRL_FAILED                       ,"control command failed"},
 {DSO_R_DSO_ALREADY_LOADED                ,"dso already loaded"},
+{DSO_R_EMPTY_FILE_STRUCTURE              ,"empty file structure"},
+{DSO_R_FAILURE                           ,"failure"},
 {DSO_R_FILENAME_TOO_BIG                  ,"filename too big"},
 {DSO_R_FINISH_FAILED                     ,"cleanup method function failed"},
+{DSO_R_INCORRECT_FILE_SYNTAX             ,"incorrect file syntax"},
 {DSO_R_LOAD_FAILED                       ,"could not load the shared library"},
 {DSO_R_NAME_TRANSLATION_FAILED           ,"name translation failed"},
 {DSO_R_NO_FILENAME                       ,"no filename"},
index 556069b9b824236f3f6d328aa560b61bab8b0066..e7ddfd5ecf799ef0352ecd4907d8c8ce89651edf 100644 (file)
@@ -1,4 +1,4 @@
-/* dso_lib.c */
+/* dso_lib.c -*- mode:C; c-file-style: "eay" -*- */
 /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
  * project 2000.
  */
@@ -390,6 +390,33 @@ int DSO_set_filename(DSO *dso, const char *filename)
        return(1);
        }
 
+char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2)
+       {
+       char *result = NULL;
+
+       if(dso == NULL || dir == NULL)
+               {
+               DSOerr(DSO_F_DSO_MERGE,ERR_R_PASSED_NULL_PARAMETER);
+               return(NULL);
+               }
+       if(filespec1 == NULL)
+               filespec1 = dso->filename;
+       if(filespec1 == NULL)
+               {
+               DSOerr(DSO_F_DSO_MERGE,DSO_R_NO_FILENAME);
+               return(NULL);
+               }
+       if((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0)
+               {
+               if(dso->merger != NULL)
+                       result = dso->merger(dso, filespec1, filespec2);
+               else if(dso->meth->dso_merger != NULL)
+                       result = dso->meth->dso_merger(dso,
+                               filespec1, filespec2);
+               }
+       return(result);
+       }
+
 char *DSO_convert_filename(DSO *dso, const char *filename)
        {
        char *result = NULL;
index 1674619d17b4f7c963a846cc369e6af538be3ba5..696e1cc84bf210abc7c4342ab61dfc8fa21f2e94 100644 (file)
@@ -1,4 +1,4 @@
-/* dso_vms.c */
+/* dso_vms.c -*- mode:C; c-file-style: "eay" -*- */
 /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
  * project 2000.
  */
@@ -63,6 +63,7 @@
 #include <openssl/dso.h>
 #ifdef OPENSSL_SYS_VMS
 #pragma message disable DOLLARID
+#include <rms.h>
 #include <lib$routines.h>
 #include <stsdef.h>
 #include <descrip.h>
@@ -89,6 +90,8 @@ static int vms_finish(DSO *dso);
 static long vms_ctrl(DSO *dso, int cmd, long larg, void *parg);
 #endif
 static char *vms_name_converter(DSO *dso, const char *filename);
+static char *vms_merger(DSO *dso, const char *filespec1,
+       const char *filespec2);
 
 static DSO_METHOD dso_meth_vms = {
        "OpenSSL 'VMS' shared library method",
@@ -103,6 +106,7 @@ static DSO_METHOD dso_meth_vms = {
 #endif
        NULL, /* ctrl */
        vms_name_converter,
+       vms_merger,
        NULL, /* init */
        NULL  /* finish */
        };
@@ -368,6 +372,128 @@ static DSO_FUNC_TYPE vms_bind_func(DSO *dso, const char *symname)
        return sym;
        }
 
+static char *vms_merger(DSO *dso, const char *filespec1, const char *filespec2)
+       {
+       int status;
+       int filespec1len, filespec2len;
+       struct FAB fab;
+#ifdef NAML$C_MAXRSS
+       struct NAML nam;
+       char esa[NAML$C_MAXRSS];
+#else
+       struct NAM nam;
+       char esa[NAM$C_MAXRSS];
+#endif
+       char *merged;
+
+       if (!filespec1) filespec1 = "";
+       if (!filespec2) filespec2 = "";
+       filespec1len = strlen(filespec1);
+       filespec2len = strlen(filespec2);
+
+       fab = cc$rms_fab;
+#ifdef NAML$C_MAXRSS
+       nam = cc$rms_naml;
+#else
+       nam = cc$rms_nam;
+#endif
+
+       fab.fab$l_fna = filespec1;
+       fab.fab$b_fns = filespec1len;
+       fab.fab$l_dna = filespec2;
+       fab.fab$b_dns = filespec2len;
+#ifdef NAML$C_MAXRSS
+       if (filespec1len > NAM$C_MAXRSS)
+               {
+               fab.fab$l_fna = -1;
+               fab.fab$b_fns = 0;
+               nam.naml$l_long_filename = filespec1;
+               nam.naml$l_long_filename_size = filespec1len;
+               }
+       if (filespec2len > NAM$C_MAXRSS)
+               {
+               fab.fab$l_dna = -1;
+               fab.fab$b_dns = 0;
+               nam.naml$l_long_defname = filespec2;
+               nam.naml$l_long_defname_size = filespec2len;
+               }
+       nam.naml$l_esa = esa;
+       nam.naml$b_ess = NAM$C_MAXRSS;
+       nam.naml$l_long_expand = esa;
+       nam.naml$l_long_expand_alloc = sizeof(esa);
+       nam.naml$b_nop = NAM$M_SYNCHK | NAM$M_PWD;
+       nam.naml$v_no_short_updase = 1;
+#else
+       nam.nam$l_esa = esa;
+       nam.nam$b_ess = NAM$C_MAXRSS;
+       nam.nam$b_nop = NAM$M_SYNCHK | NAM$M_PWD;
+#endif
+       fab.fab$l_nam = &nam;
+
+       status = sys$parse(&fab, 0, 0);
+
+       if(!$VMS_STATUS_SUCCESS(status))
+               {
+               unsigned short length;
+               char errstring[257];
+               struct dsc$descriptor_s errstring_dsc;
+
+               errstring_dsc.dsc$w_length = sizeof(errstring);
+               errstring_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
+               errstring_dsc.dsc$b_class = DSC$K_CLASS_S;
+               errstring_dsc.dsc$a_pointer = errstring;
+
+               *sym = NULL;
+
+               status = sys$getmsg(status, &length, &errstring_dsc, 1, 0);
+
+               if (!$VMS_STATUS_SUCCESS(status))
+                       lib$signal(status); /* This is really bad.  Abort!  */
+               else
+                       {
+                       errstring[length] = '\0';
+
+                       DSOerr(DSO_F_VMS_MERGER,DSO_R_FAILURE);
+                       ERR_add_error_data(9,
+                               "filespec \"", filespec1, "\", ",
+                               "defaults \"", filespec2, "\": "
+                               errstring);
+                       }
+               return(NULL);
+               }
+#ifdef NAML$C_MAXRSS
+       if (nam.naml$l_long_expand_size)
+               {
+               merged = OPENSSL_malloc(nam.naml$l_long_expand_size + 1);
+               if(!merged)
+                       goto malloc_err;
+               strncpy(merged, nam.naml$l_long_expand,
+                       nam.naml$l_long_expand_size);
+               merged[nam.naml$l_long_expand_size] = '\0';
+               }
+       else
+               {
+               merged = OPENSSL_malloc(nam.naml$l_esl + 1);
+               if(!merged)
+                       goto malloc_err;
+               strncpy(merged, nam.naml$l_esa,
+                       nam.naml$l_esl);
+               merged[nam.naml$l_esl] = '\0';
+               }
+#else
+       merged = OPENSSL_malloc(nam.nam$l_esl + 1);
+       if(!merged)
+               goto malloc_err;
+       strncpy(merged, nam.nam$l_esa,
+               nam.nam$l_esl);
+       merged[nam.nam$l_esl] = '\0';
+#endif
+       return(merged);
+ malloc_err:
+       DSOerr(DSO_F_VMS_MERGER,
+               ERR_R_MALLOC_FAILURE);
+       }
+
 static char *vms_name_converter(DSO *dso, const char *filename)
        {
         int len = strlen(filename);
index af8586d7542364c801b26c3c1783440274f7dd51..4ce9a5d45c8cfb9ce3e1829be9f5c34b89a5d3b2 100644 (file)
@@ -1,4 +1,4 @@
-/* dso_win32.c */
+/* dso_win32.c -*- mode:C; c-file-style: "eay" -*- */
 /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
  * project 2000.
  */
@@ -83,6 +83,8 @@ static int win32_finish(DSO *dso);
 static long win32_ctrl(DSO *dso, int cmd, long larg, void *parg);
 #endif
 static char *win32_name_converter(DSO *dso, const char *filename);
+static char *win32_merger(DSO *dso, const char *filespec1,
+       const char *filespec2);
 
 static DSO_METHOD dso_meth_win32 = {
        "OpenSSL 'win32' shared library method",
@@ -97,6 +99,7 @@ static DSO_METHOD dso_meth_win32 = {
 #endif
        NULL, /* ctrl */
        win32_name_converter,
+       win32_merger,
        NULL, /* init */
        NULL  /* finish */
        };
@@ -248,6 +251,304 @@ static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname)
        return((DSO_FUNC_TYPE)sym);
        }
 
+struct file_st
+       {
+       const char *node; int nodelen;
+       const char *device; int devicelen;
+       const char *predir; int predirlen;
+       const char *dir; int dirlen;
+       const char *file; int filelen;
+       }
+
+static struct file_st *win32_splitter(DSO *dso, const char *filename,
+       int assume_last_is_dir)
+       {
+       struct file_st *result = NULL;
+       enum { IN_NODE, IN_DEVICE, IN_FILE } position;
+       const char *start = filename;
+
+       if (!filename)
+               {
+               DSOerr(DSO_F_WIN32_MERGER,DSO_R_NO_FILENAME);
+               goto err;
+               }
+
+       result = OPENSSL_malloc(sizeof(struct file_st));
+       if(result == NULL)
+               {
+               DSOerr(DSO_F_WIN32_MERGER,
+                       ERR_R_MALLOC_FAILURE);
+               return(NULL);
+               }
+
+       memset(result, 0, sizeof(struct file_st));
+       position = IN_DEVICE;
+
+       if(filename[0] == '\\' && filename[1] == '\\'
+               || filename[0] == '/' && filename[1] == '/')
+               {
+               position = IN_NODE;
+               filename += 2;
+               start = filename;
+               result->node = start;
+               }
+
+       do
+               {
+               switch(filename[0])
+                       {
+               case ':':
+                       if(position != IN_DEVICE)
+                               {
+                               DSOerr(DSO_F_WIN32_MERGER,
+                                       DSO_R_INCORRECT_FILE_SYNTAX);
+                               goto err;
+                               }
+                       result->device = start;
+                       result->devicelen = filename - start;
+                       position = IN_FILE;
+                       start = ++filename;
+                       result->dir = start;
+                       break;
+               case '\\':
+               case '/':
+                       if(position == IN_NODE)
+                               {
+                               result->nodelen = filename - start;
+                               position = IN_FILE;
+                               start = ++filename;
+                               result->dir = start;
+                               }
+                       else
+                               {
+                               filename++;
+                               result->dirlen += filename - start;
+                               }
+                       break;
+               case '\0':
+                       if(position == IN_NODE)
+                               {
+                               result->nodelen = filename - start;
+                               }
+                       else
+                               {
+                               if(filename - start > 0)
+                                       {
+                                       if (assume_last_is_dir)
+                                               {
+                                               result->devicelen += filename - start;
+                                               }
+                                       else
+                                               {
+                                               result->file = start;
+                                               result->filelen = filename - start;
+                                               }
+                                       }
+                               }
+                       break;
+               default:
+                       filename++;
+                       break;
+                       }
+               }
+       while(*filename);
+
+       if(!result->nodelen) result->node = NULL;
+       if(!result->devicelen) result->devicce = NULL;
+       if(!result->dirlen) result->dir = NULL;
+       if(!result->filelen) result->file = NULL;
+
+       return(result);
+       }
+
+static char *win32_joiner(DSO *dso, const file_st *file_split)
+       {
+       int len = 0, offset = 0;
+       char *result = NULL;
+       const char *start;
+
+       if(!file_split)
+               {
+               DSOerr(DSO_F_WIN32_MERGER,
+                               ERR_R_PASSED_NULL_PARAMETER);
+               return(NULL);
+               }
+       if(file_split->node)
+               {
+               len += 2 + file_split->nodelen; /* 2 for starting \\ */
+               if(file_split->predir || file_split->dir || file_split->file)
+                       len++;  /* 1 for ending \ */
+               }
+       else if(file_split->device)
+               {
+               len += file_split->devicelen + 1; /* 1 for ending : */
+               }
+       len += file_split->predirlen;
+       if(file_split->predir && (file_split->dir || file_split->file))
+               {
+               len++;  /* 1 for ending \ */
+               }
+       len += file_split->dirlen;
+       if(file_split->dir && file_split->file)
+               {
+               len++;  /* 1 for ending \ */
+               }
+       len += file_split->filelen;
+
+       if(!len)
+               {
+               DSOerr(DSO_F_WIN32_MERGER, DSO_R_EMPTY_FILE_STRUCTURE);
+               return(NULL);
+               }
+
+       result = OPENSSL_malloc(len + 1);
+       if (!result)
+               {
+               DSOerr(DSO_F_WIN32_MERGER,
+                       ERR_R_MALLOC_FAILURE);
+               return(NULL);
+               }
+
+       if(file_split->node)
+               {
+               strcpy(&result[offset], "\\\\"); offset += 2;
+               strncpy(&result[offset], file_split->node,
+                       file_split->nodelen); offset += file_split->nodelen;
+               if(file_split->predir || file_split->dir || file_split->file)
+                       {
+                       result[offset] = '\\'; offset++;
+                       }
+               }
+       else if(file_split->device)
+               {
+               strncpy(&result[offset], file_split->device,
+                       file_split->devicelen); offset += file_split->devicelen;
+               result[offset] = ':'; offset++;
+               }
+       start = file_split->predir;
+       while(file_split->predirlen > (start - file_split->predir))
+               {
+               const char *end = strnchr(start, '/',
+                       file_split->predirlen - (start - file_split->predir));
+               if(!end)
+                       end = start
+                               + file_split->predirlen
+                               - (start - file_split->predir);
+               strncpy(&result[offset], start,
+                       end - start); offset += end - start;
+               result[offset] = '\\'; offset++;
+               start = end + 1;
+               }
+       if(file_split->predir && (file_split->dir || file_split->file))
+               {
+               result[offset] = '\\'; offset++;
+               }
+       start = file_split->dir;
+       while(file_split->dirlen > (start - file_split->dir))
+               {
+               const char *end = strnchr(start, '/',
+                       file_split->dirlen - (start - file_split->dir));
+               if(!end)
+                       end = start
+                               + file_split->dirlen
+                               - (start - file_split->dir);
+               strncpy(&result[offset], start,
+                       end - start); offset += end - start;
+               result[offset] = '\\'; offset++;
+               start = end + 1;
+               }
+       if(file_split->dir && file_split->file)
+               {
+               result[offset] = '\\'; offset++;
+               }
+       strncpy(&result[offset], file_split->file,
+               file_split->filelen); offset += file_split->filelen;
+       result[offset] = '\0';
+       return(result);
+       }
+
+static char *win32_merger(DSO *dso, const char *filespec1, const char *filespec2)
+       {
+       char *merged = NULL;
+       struct file_st *filespec1_split = NULL;
+       struct file_st *filespec2_split = NULL;
+
+       if(!filespec1 && !filespec2)
+               {
+               DSOerr(DSO_F_WIN32_MERGER,
+                               ERR_R_PASSED_NULL_PARAMETER);
+               return(NULL);
+               }
+       if (!filespec2)
+               {
+               merged = OPENSSL_malloc(strlen(filespec1) + 1);
+               if(!merged)
+                       {
+                       DSOerr(DSO_F_WIN32_MERGER,
+                               ERR_R_MALLOC_FAILURE);
+                       return(NULL);
+                       }
+               strcpy(merged, filespec1);
+               }
+       else if (!filespec1)
+               {
+               merged = OPENSSL_malloc(strlen(filespec2) + 1);
+               if(!merged)
+                       {
+                       DSOerr(DSO_F_WIN32_MERGER,
+                               ERR_R_MALLOC_FAILURE);
+                       return(NULL);
+                       }
+               strcpy(merged, filespec2);
+               }
+       else
+               {
+               filespec1_split = win32_splitter(dso, filespec1, 1);
+               if (!filespec1_split)
+                       {
+                       DSOerr(DSO_F_WIN32_MERGER,
+                               ERR_R_MALLOC_FAILURE);
+                       return(NULL);
+                       }
+               filespec2_split = win32_splitter(dso, filespec2, 0);
+               if (!filespec1_split)
+                       {
+                       DSOerr(DSO_F_WIN32_MERGER,
+                               ERR_R_MALLOC_FAILURE);
+                       OPENSSL_free(filespec1_split);
+                       return(NULL);
+                       }
+
+               /* Fill in into filespec1_split */
+               if (!filespec1_split->node && !filespec1_split->device)
+                       {
+                       filespec1_split->node = filespec2_split->node;
+                       filespec1_split->nodelen = filespec2_split->nodelen;
+                       filespec1_split->device = filespec2_split->device;
+                       filespec1_split->devicelen = filespec2_split->devicelen;
+                       }
+               if (!filespec1_split->dir)
+                       {
+                       filespec1_split->dir = filespec2_split->dir;
+                       filespec1_split->dirlen = filespec2_split->dirlen;
+                       }
+               else if (filespec1_split->dir[0] != '\\'
+                       && filespec1_split->dir[0] != '/')
+                       {
+                       filespec1_split->predir = filespec2_split->dir;
+                       filespec1_split->predirlen = filespec2_split->dirlen;
+                       }
+               if (!filespec1_split->file)
+                       {
+                       filespec1_split->file = filespec2_split->file;
+                       filespec1_split->filelen = filespec2_split->filelen;
+                       }
+
+               merged = win32_joiner(dso, filespec1_split);
+               }
+       return(merged);
+       }
+
 static char *win32_name_converter(DSO *dso, const char *filename)
        {
        char *translated;