1#if defined( __VMS) && !defined( OPENSSL_NO_DECC_INIT) && \
2 defined( __DECC) && !defined( __VAX) && (__CRTL_VER >= 70301000)
3# define USE_DECC_INIT 1
4#endif
5
6#ifdef USE_DECC_INIT
7
8/*-
9 * 2010-04-26 SMS.
10 *
11 *----------------------------------------------------------------------
12 *
13 *       decc_init()
14 *
15 *    On non-VAX systems, uses LIB$INITIALIZE to set a collection of C
16 *    RTL features without using the DECC$* logical name method.
17 *
18 *----------------------------------------------------------------------
19 */
20
21# include <stdio.h>
22# include <stdlib.h>
23# include <unixlib.h>
24
25/* Global storage. */
26
27/* Flag to sense if decc_init() was called. */
28
29int decc_init_done = -1;
30
31/* Structure to hold a DECC$* feature name and its desired value. */
32
33typedef struct {
34    char *name;
35    int value;
36} decc_feat_t;
37
38/*
39 * Array of DECC$* feature names and their desired values. Note:
40 * DECC$ARGV_PARSE_STYLE is the urgent one.
41 */
42
43decc_feat_t decc_feat_array[] = {
44    /* Preserve command-line case with SET PROCESS/PARSE_STYLE=EXTENDED */
45    {"DECC$ARGV_PARSE_STYLE", 1},
46
47    /* Preserve case for file names on ODS5 disks. */
48    {"DECC$EFS_CASE_PRESERVE", 1},
49
50    /*
51     * Enable multiple dots (and most characters) in ODS5 file names, while
52     * preserving VMS-ness of ";version".
53     */
54    {"DECC$EFS_CHARSET", 1},
55
56    /* List terminator. */
57    {(char *)NULL, 0}
58};
59
60/* LIB$INITIALIZE initialization function. */
61
62static void decc_init(void)
63{
64    char *openssl_debug_decc_init;
65    int verbose = 0;
66    int feat_index;
67    int feat_value;
68    int feat_value_max;
69    int feat_value_min;
70    int i;
71    int sts;
72
73    /* Get debug option. */
74    openssl_debug_decc_init = getenv("OPENSSL_DEBUG_DECC_INIT");
75    if (openssl_debug_decc_init != NULL) {
76        verbose = strtol(openssl_debug_decc_init, NULL, 10);
77        if (verbose <= 0) {
78            verbose = 1;
79        }
80    }
81
82    /* Set the global flag to indicate that LIB$INITIALIZE worked. */
83    decc_init_done = 1;
84
85    /* Loop through all items in the decc_feat_array[]. */
86
87    for (i = 0; decc_feat_array[i].name != NULL; i++) {
88        /* Get the feature index. */
89        feat_index = decc$feature_get_index(decc_feat_array[i].name);
90        if (feat_index >= 0) {
91            /* Valid item.  Collect its properties. */
92            feat_value = decc$feature_get_value(feat_index, 1);
93            feat_value_min = decc$feature_get_value(feat_index, 2);
94            feat_value_max = decc$feature_get_value(feat_index, 3);
95
96            /* Check the validity of our desired value. */
97            if ((decc_feat_array[i].value >= feat_value_min) &&
98                (decc_feat_array[i].value <= feat_value_max)) {
99                /* Valid value.  Set it if necessary. */
100                if (feat_value != decc_feat_array[i].value) {
101                    sts = decc$feature_set_value(feat_index,
102                                                 1, decc_feat_array[i].value);
103
104                    if (verbose > 1) {
105                        fprintf(stderr, " %s = %d, sts = %d.\n",
106                                decc_feat_array[i].name,
107                                decc_feat_array[i].value, sts);
108                    }
109                }
110            } else {
111                /* Invalid DECC feature value. */
112                fprintf(stderr,
113                        " INVALID DECC$FEATURE VALUE, %d: %d <= %s <= %d.\n",
114                        feat_value,
115                        feat_value_min, decc_feat_array[i].name,
116                        feat_value_max);
117            }
118        } else {
119            /* Invalid DECC feature name. */
120            fprintf(stderr,
121                    " UNKNOWN DECC$FEATURE: %s.\n", decc_feat_array[i].name);
122        }
123    }
124
125    if (verbose > 0) {
126        fprintf(stderr, " DECC_INIT complete.\n");
127    }
128}
129
130/* Get "decc_init()" into a valid, loaded LIB$INITIALIZE PSECT. */
131
132# pragma nostandard
133
134/*
135 * Establish the LIB$INITIALIZE PSECTs, with proper alignment and other
136 * attributes.  Note that "nopic" is significant only on VAX.
137 */
138# pragma extern_model save
139
140# if __INITIAL_POINTER_SIZE == 64
141#  define PSECT_ALIGN 3
142# else
143#  define PSECT_ALIGN 2
144# endif
145
146# pragma extern_model strict_refdef "LIB$INITIALIZ" PSECT_ALIGN, nopic, nowrt
147const int spare[8] = { 0 };
148
149# pragma extern_model strict_refdef "LIB$INITIALIZE" PSECT_ALIGN, nopic, nowrt
150void (*const x_decc_init) () = decc_init;
151
152# pragma extern_model restore
153
154/* Fake reference to ensure loading the LIB$INITIALIZE PSECT. */
155
156# pragma extern_model save
157
158int LIB$INITIALIZE(void);
159
160# pragma extern_model strict_refdef
161int dmy_lib$initialize = (int)LIB$INITIALIZE;
162
163# pragma extern_model restore
164
165# pragma standard
166
167#else                           /* def USE_DECC_INIT */
168
169/* Dummy code to avoid a %CC-W-EMPTYFILE complaint. */
170int decc_init_dummy(void);
171
172#endif                          /* def USE_DECC_INIT */
173